Cargo
Require libraries without cluttering your namespace.
Description
Consider these two versions of the same library:
# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end
# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
If you want to use both of them in your application, require and
load will be of little help. Consider what happens when you require
both libraries:
>> require "foo-1.0.0"
=> true
>> require "foo-2.0.0"
=> true
>> Foo::VERSION
=> "2.0.0"
As both files are opening the same class, there's no way for you to use them independently.
Cargo solves that problem in a very simple way:
>> Foo1 = import("foo-1.0.0")
=> #<Module:0x000001009ffa28>::Foo
>> Foo2 = import("foo-2.0.0")
=> #<Module:0x000001009f2828>::Foo
>> Foo1::VERSION
=> "1.0.0"
>> Foo2::VERSION
=> "2.0.0"
How does it work?
The command Kernel.load accepts a second parameter, which value is
false by default. When the passed value is true, the script is
executed under an anonymous module, protecting the calling program's
global namespace. No local variables in the loaded file are propagated
to the loading environment.
By using a global module as a temporal storage, it is possible to transfer a value from the anonymous module to the caller program.
Usage
After requiring cargo in the calling program, two methods will
be available: import and export. Both use the global module
Cargo for temporal storage.
This is how you will use it in the calling program:
$ cat calling_program.rb
require "cargo"
MyFoo = import("foo")
And for that to work, the imported library should look like this:
$ cat foo.rb
class Foo
  VERSION = "1.0.0"
end
export(Foo)
Note that you can only export one value per file. Multiple calls to
export just change the value to be exported. This constraint is in
place in order to make for a simple and clean implementation.
How to prepare your library for Cargo
In your library entry point, you need to use export and provide a value. As
the export method won't be available unless the caller is using
Cargo, you can make a conditional call:
export(Foo) if defined?(export)
If your library has just one file, that single line will make your code ready to be imported. Otherwise, you will need to require Cargo and make sure you don't mix import with require for local files.
Installation
$ gem install cargo
License
Copyright (c) 2010 Michel Martens & Damian Janowski
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.