Capsule

Description

Capsule is a subclass of Module. A module which is an instance of the Capsule class encapsulates in its scope the top-level methods, top-level constants, and instance variables defined in a Ruby script (and its dependent files) loaded by a Ruby program. This allows use of script files to define objects that can be loaded into a program in much the same way that objects can be loaded from YAML or Marshaled files. There is also an autoimport method which functions like Ruby’s autoload but based on is Capsule.load.

Resources

Synopsis

To encapsulate a script in a Capsule:

myscript = Capsule.new('myscript.rb')

If the script is in Ruby’s $LOAD_PATH, then you can use Capsule.load.

myscript = Capsule.load('myscript.rb')

Here is an example:

# myscript.rb

VALUE = [1,2,3]

def run
  puts "#{self} is running."
end

And the encapsulating program:

# program.rb:

require 'capsule'

myscript = Capsule.load("myscript.rb")

p myscript::VALUE

myscript.run

Running ‘program.rb` will result in:

$ ruby program.rb
[1, 2, 3]
#<Capsule:myscript.rb> is running.

Usage

Capsule modules are instantiated with Capsule.new(main_file) or the alias Capsule.load(main_file). All the top-level constants and top-level methods that are defined in the main_file and its dependent local files (see below) are scoped in the same Capsule module, and are thereby available to the calling program.

The main_file can load or require other files with load and require, as usual. These methods, in the Capsule context, add some behavior to the Kernel load and require methods: Capsule#load and Capsule#require first search for files relative to the main_file‘s dir. Files loaded in this way (“dependent local files”) are treated like the script file itself: top-level definitions are added to the script module that is returned by load or require.

Both Capsule#load and Capsule#require fall back to the Kernel versions if the file is not found locally. Hence, other ruby libraries can be loaded and required as usual, assuming their names do not conflict with local file names. Definitions from those files go into the usual scope (typically global). The normal ruby load and require behavior can be forced by calling Kernel.load and Kernel.require.

A Capsule immitates the way the top-level ruby context works, so a ruby file that was originally intended to be run from the top level, defining top-level constants and top-level methods, can also be run as a Capsule, and its top-level constants and top-level methods are wrapped in the script’s scope. The difference between this behavior and simply wrapping the loaded definitions in an anonymous module using Kernel.load(main_file, true) is that the top-level methods and top-level constants defined in the script are accessible using the Capsule instance.

The top-level definitions of a Capsule can be accessed after it has been loaded, as follows:

script.meth

  • Call a method defined using def meth or def self.meth in the script file.

script::K

  • Access a class, module, or constant defined using K = val in the script file.

An “input” can be passed to the script before loading. Simply call Capsule.new (or Capsule.load) with a block. The block is passed a single argument, the Capsule module, and executed before the files are loaded into the Capsule’s scope. Setting a constant in this block makes the constant available to the script during loading. For example:

script = Capsule.load("my-script.rb") { |capsule| capsule::INPUT = 3 }

Note that all methods defined in the script file are both instance methods of the module and methods of the module instance (the effect of Module#module_function). So include-ing a Capsule module in a class will give instances of the class all the methods and constants defined in the script, and they will reference the instance’s instance variables, rather than the Capsule module’s instance variables.

The Capsule class was inspired by Nobu Nokada’s suggestion in ruby-talk.org/62727, in a thread (started in ruby-talk.org/62660) about how to use ruby script files as specifications of objects.

Installation

To install with RubyGems simply open a console and type:

gem install capsule

Local installation requires Setup.rb (gem install setup), then download the tarball package and type:

tar -xvzf capsule-1.0.0.tgz
cd capsule-1.0.0
sudo setup.rb all

Windows users use ‘ruby setup.rb all’.

(AGPL 3 License)

Copyright © 2007 Thomas Sawyer Copyright © 2004 Joel VanderWerf

Capsule is based on Joel VanderWerf’s Script library.

Unless otherwise agreed upon by the copyright holder, this program is ditributed under the terms of the GNU Affero General Public License v3.

See COPYING.rdoc file for details.