Skip to content
This repository was archived by the owner on Apr 7, 2026. It is now read-only.

General usage

7rans edited this page Jan 12, 2013 · 3 revisions

Using Rolled Libraries

Require and Load

Using a rolled Ruby library isn't much different than using a non-rolled one. For instance the demo app incuded in the Realms distribution can be tested (after rolling it in) from irb just by typing:

    require 'fruitapp/tryme'

The Realm system will see that 'fruitapp' is a rolled library, automatically select the most recent version if there is more than one, then proceed to require tryme.rb from it.

You might notice from this explanation, that Realms does not require files in the exact same manner a Ruby. Instead of searching for a matching paths from all project via the $LOAD_PATH, Realms assumes the first part of the path is the library name. This assumption is usually correct, and a good project designer will make sure it is correct for their project. This assumption increases load efficiency nearly 2-3 times.

Rather then have Realms automatically select the latest version of a library, the version can be manually activated via a version constraint. This is most easily achieved with the provided library Kernel method.

    library 'fruitapp', '= 1.0'
    require 'fruitapp/tryme'

So in this example, specifically version 1.0 of fruitapp will be used. The version parameter is optional. When no version constraint is given the most recent available version is selected. When Realms activates a particular version of a library, other versions are no longer available. Any subsequent attempt to activate a different version will raise an error.

The Library Class

The library method does more than simply select a version. The library method also returns returns a Libraryobject. This Kernel method is actually just a shortcut for instantiating a new Library object via the Library.instance method.

    Library.instance('fruitapp')   #=> #<Library fruitapp/1.0.1>

The instance method require the library name as the first parameter. The name is then used as the ledger key to track the library. The difference between #instance and #open is that #open will raise an error if the library is not found and can also take a block which yields on the library. In addition, there is a shorter alias for #instance provided as #[]. Like #instance, it too will not raise an error if the the library is not found, but will simply return nil.

    Library['fruitapp']  #=> #<Library fruitapp/1.0.1>
    Library['notthere']  #=> nil

Library is multiton, which means only one instance exists per name. Calling #library, Library.instance, Library.open or Library.[] repeatedly using the same name will return the very same Library object.

When selecting a version, the constraint is a simple string starting with an operator, like = or >=, followed by the string representaion of a version number. For instance,

    Library.instance('fruitapp', '~> 1.0')     #=> #<Library fruitapp/0.9>
    Library.instance('fruitapp', '== 2.0')     #=> #<Library fruitapp/2.0>

Once a version is selected the version can not be changed. A Library::VersionConflict will be raised if one attempts to do so.

NOTE: This restriction has put in place to prevent conflicts which can arise when libraries extend core functionality. Certainly it would be nice if multiple-versions could work harmoniously, but this is not even remotely possible until such time as Ruby supports selector namespaces. In the future though we may be able to reduce the restrinction to just the use of #require and #load.

Now, with a library in hand, the most obvious method provided is #require.

    library('fruitapp').require 'tryme'

As you can see this is pure OOP. You could store the reference to the library for later access, even pass it around as an argument.

    fruitlib = Library.open('fruitapp', '=1.0')
    fruitlib.require 'tryme'

Related Locations

NOTE: This section is not wholey correct.

To facilitate access to file locations pertaining to a library, Realms provides some convenient methods. Normally this information is accessed by using rbconfig.rb and building a path based on information in the Config::CONFIG hash. For instance, Config:CONFIG['datadir'] on a Debian system points to /usr/share. With Roll you can look up the data dir specific to the current library via the #datadir method, and likewise for the other directories. Here's a example rundown with resolutions for a Debian system.

    # library directory
    library('fruitapp').libdir           #=> [ "/usr/local/lib/site_ruby/1.8/fruitapp/1.0.0/" ]

    # configuration dir
    library('fruitapp').confdir          #=> "/etc/fruitapp/"

    # versioned data dir
    library('fruitapp').datadir          #=> "/usr/share/fruitapp/1.0.0/"

    # ensure non-versioned data dir
    library('fruitapp').datadir(true)    #=> "/usr/share/fruitapp/"

Another way to access these locations is via Ruby's own Config module. Eg. Config.datadir('fruitapp'). This provides a wholly general interface to this information, irregardless of the system providing it, whether it be Realms, Gems or some other system.

With Realms, a project's bin/ directory is not versioned, unlike the lib/ directory. It doesn need to be because a simple convention makes it possible to version executable files: In so far as an executable is to be versioned (and it's generally a good idea to do so) one should wrap the logic in a file under the versioned lib/ directry, then simply requiring or load the lib file into the executable file. It's a simple enough practice and doing it in this manner means that no specialized action is required of any packaging or distribution system. Here is a good example of such a file.

    #!/usr/bin/env ruby
    version = "> 0"
    if ARGV.size > 0 && ARGV[0][0]==95 && ARGV[0][-1]==95
      if Library::Version.correct?(ARGV[0][1..-2])
        version = ARGV[0][1..-2]
        ARGV.shift
      end
    end
    library 'camping', version
    load 'camping'

Library Metadata

Additional meta-information may also be accessed via the library interface. This is optional information that may or may not be provided by the project developers.

To tell if any metadata has been provided, query the library with the #metadata? call. If true, then other information will be availabe. For instance:

    library('fruitapp').title     #=> "Fruit Basket Application"
    library('fruitapp').summary   #=> "Example application to demonstrate realms.rb."
    library('fruitapp').author    #=> "Trans"

Clone this wiki locally