Class: Capsule

Class | Capsule
In: | lib/more/facets/capsule.rb
Parent: | Module

# Capsule

A Capsule is subclass of Module. It encapsulates an extenal script as a funcitons 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 file (and its subfiles) 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 Marshal files.

See intro.txt for an overview.

### Methods

include include_script load load load_in_module load_path_lookup new require

### Classes and Modules

Class Capsule::MissingFile

### Attributes

load_path | [R] | An array of paths to search for scripts. This has the same semantics as `$:`, alias `$LOAD_PATH`, excpet that it is local to this script. The path of the current script is added automatically (equivalent to ’.’)
loaded_features | [R] | A hash that maps `filename=>true` for each file that has been required locally by the script. This has the same semantics as `$"`, alias `$LOADED_FEATURES`, except that it is local to this script.
main_file | [R] | The script file with which the Import was instantiated.

### Public Class methods

load(main_file, options=nil, &block)

As with new but will search Ruby‘s $LOAD_PATH first.

[Source]

    # File lib/more/facets/capsule.rb, line 78
        def load(main_file, options=nil, &block)
          file = nil
          $LOAD_PATH.each do |path|
            break if file = File.file?(File.join(path, main_file))
            #break if file = Dir.glob(File.join(path, main_file)+'{,.rb,.'+DLEXT+'}')[0]
          end
          new(file || main_file, options=nil, &block)
        end

new(main_file, options=nil, &block)

Creates new Capsule, and loads main_file in the scope of the script. If a block is given, the script is passed to it before loading from the file, and constants can be defined as inputs to the script.

[Source]

    # File lib/more/facets/capsule.rb, line 92
      def initialize(main_file, options=nil, &block)
        extend self

        options ||= {}

        @main_file       = File.expand_path(main_file)
        @load_path       = options[:load_path] || []
        #@load_path |= [File.dirname(@main_file)]  # before or after?
        @loaded_features = options[:loaded_features] || {}

        # TODO In order to load/require at the instance level.
        # This needs to be in a separate namespace however
        # b/c it can interfere with what is expected.
        #[ :require, :load ].each{ |meth|
        #  m = method(meth)
        #  define_method(meth) do |*args| m.call(*args) end
        #}

        module_eval(&block) if block
        extend self

        load_in_module(main_file)
      end

### Public Instance methods

include(*mods)

[Source]

    # File lib/more/facets/capsule.rb, line 204
      def include(*mods)
        super
        extend self
      end

include_script(file)

[Source]

    # File lib/more/facets/capsule.rb, line 193
      def include_script(file)
        include self.class.new(file, :load_path=>load_path, :loaded_features=>loaded_features)
      rescue Errno::ENOENT => e
        if /#{file}$/ =~ e.message
          raise MissingFile, e.message
        else
          raise
        end
      end

load(file, wrap = false)

Loads file into the capsule. Searches relative to the local dir, that is, the dir of the file given in the original call to `Capsule.load(file)`, loads the file, if found, into this Capsule‘s scope, and returns true. If the file is not found, falls back to `Kernel.load`, which searches on `$LOAD_PATH`, loads the file, if found, into global scope, and returns true. Otherwise, raises `LoadError`.

The wrap argument is passed to `Kernel.load` in the fallback case, when the file is not found locally.

Typically called from within the main file to load additional sub files, or from those sub files.

[Source]

    # File lib/more/facets/capsule.rb, line 143
      def load(file, wrap = false)
        load_in_module(File.join(@dir, file))
        true
      rescue MissingFile
        super
      end

load_in_module(file)

Loads file in this module‘s context. Note that `__FILE__` and `__LINE__` work correctly in file. Called by load and require; not normally called directly.

[Source]

    # File lib/more/facets/capsule.rb, line 183
      def load_in_module(file)
        module_eval(IO.read(file), File.expand_path(file))
      rescue Errno::ENOENT => e
        if /#{file}$/ =~ e.message
          raise MissingFile, e.message
        else
          raise
        end
      end

load_path_lookup(feature)

Lookup feature in load path.

[Source]

    # File lib/more/facets/capsule.rb, line 118
      def load_path_lookup(feature)
        paths = File.join('{' + @load_path.join(',') + '}', feature + '{,.rb,.rbs}')
        files = Dir.glob(paths)
        match = files.find{ |f| ! @loaded_features.include?(f) }
        return match
      end

require(feature)

Analogous to `Kernel#require`. First tries the local dir, then falls back to `Kernel#require`. Will load a given feature only once.

Note that extensions (*.so, *.dll) can be required in the global scope, as usual, but not in the local scope. (This is not much of a limitation in practice—you wouldn‘t want to load an extension more than once.) This implementation falls back to `Kernel#require` when the argument is an extension or is not found locally.

[Source]

    # File lib/more/facets/capsule.rb, line 164
      def require(feature)
        file = load_path_lookup(feature)
        return super unless file
        begin
          @loaded_features[file] = true
          load_in_module(file)
        rescue MissingFile
          @loaded_features[file] = false
          super
        end
      end

[Validate]