Class: Capsule
Overview
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.
Defined Under Namespace
Classes: MissingFile
Constant Summary collapse
- SUFFIXES =
Ruby script extensions to automatically try when searching for a script on the load_path.
['.rb', '.rbs']
Instance Attribute Summary collapse
-
#load_path ⇒ Object
readonly
An array of paths to search for scripts.
-
#loaded_features ⇒ Object
readonly
A hash that maps
filename=>true
for each file that has been required locally by the script. -
#main_file ⇒ Object
readonly
The script file with which the import was instantiated.
Class Method Summary collapse
-
.load(main_file, options = nil, &block) ⇒ Object
As with #new but will search Ruby’s $LOAD_PATH first.
Instance Method Summary collapse
-
#include(*mods) ⇒ Object
Checks the class of each
mods
. -
#include_script(file) ⇒ Object
Create a new Capsule for a script and include it into the current capsule.
-
#initialize(main_file, options = nil, &block) ⇒ Capsule
constructor
Creates new Capsule, and loads main_file in the scope of the script.
-
#inspect ⇒ Object
Give inspection of Capsule with script file name.
-
#load(file, wrap = false) ⇒ Object
Loads file into the capsule.
-
#load_in_module(file) ⇒ Object
Loads file in this module’s context.
-
#load_path_lookup(feature) ⇒ Object
Lookup feature in load path.
-
#require(feature) ⇒ Object
Analogous to
Kernel#require
.
Constructor Details
#initialize(main_file, options = nil, &block) ⇒ Capsule
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.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/capsule.rb', line 59 def initialize(main_file, =nil, &block) ||= {} @main_file = File.(main_file) @load_path = [:load_path] || [] @loaded_features = [:loaded_features] || {} @extend = true # default @extend = [:extend] if .key?(:extend) ## add script's path to load_path ## TODO: should we be doing this? @load_path |= [File.dirname(@main_file)] ## if @extend (the default) module extends itself extend self if @extend module_eval(&block) if block load_in_module(main_file) end |
Instance Attribute Details
#load_path ⇒ Object (readonly)
An array of paths to search for scripts. This has the same semantics as $:
, alias $LOAD_PATH
, except that it is local to this script. The path of the current script is added automatically.
34 35 36 |
# File 'lib/capsule.rb', line 34 def load_path @load_path end |
#loaded_features ⇒ Object (readonly)
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.
40 41 42 |
# File 'lib/capsule.rb', line 40 def loaded_features @loaded_features end |
#main_file ⇒ Object (readonly)
The script file with which the import was instantiated.
23 24 25 |
# File 'lib/capsule.rb', line 23 def main_file @main_file end |
Class Method Details
.load(main_file, options = nil, &block) ⇒ Object
As with #new but will search Ruby’s $LOAD_PATH first. This will also try ‘.rb` extensions, like require does.
45 46 47 48 49 50 51 52 53 |
# File 'lib/capsule.rb', line 45 def self.load(main_file, =nil, &block) file = nil $LOAD_PATH.each do |path| file = File.join(path, main_file) break if file = File.file?(file) break if file = Dir.glob(file + '{' + SUFFIXES.join(',') + '}').first end new(file || main_file, =nil, &block) end |
Instance Method Details
#include(*mods) ⇒ Object
Checks the class of each mods
. If a String, then calls #include_script, otherwise behaves like normal #include.
142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/capsule.rb', line 142 def include(*mods) mods.reverse_each do |mod| case mod when String include_script(mod) else super(mod) extend self if @extend end end end |
#include_script(file) ⇒ Object
Create a new Capsule for a script and include it into the current capsule.
156 157 158 159 160 161 162 163 164 165 |
# File 'lib/capsule.rb', line 156 def include_script(file) include self.class.new(file, :load_path=>load_path, :loaded_features=>loaded_features, :extend=>false) rescue Errno::ENOENT => e if /#{file}$/ =~ e. raise MissingFile, e. else raise end extend self if @extend end |
#inspect ⇒ Object
Give inspection of Capsule with script file name.
183 184 185 |
# File 'lib/capsule.rb', line 183 def inspect # :nodoc: "#<#{self.class}:#{main_file}>" end |
#load(file, wrap = false) ⇒ Object
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.
105 106 107 108 109 110 111 112 |
# File 'lib/capsule.rb', line 105 def load(file, wrap = false) file = load_path_lookup(feature) return super unless file load_in_module(file) #File.join(@dir, file)) true rescue MissingFile super end |
#load_in_module(file) ⇒ Object
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.
171 172 173 174 175 176 177 178 179 |
# File 'lib/capsule.rb', line 171 def load_in_module(file) module_eval(IO.read(file), File.(file)) rescue Errno::ENOENT => e if /#{file}$/ =~ e. raise MissingFile, e. else raise end end |
#load_path_lookup(feature) ⇒ Object
Lookup feature in load path.
84 85 86 87 88 89 |
# File 'lib/capsule.rb', line 84 def load_path_lookup(feature) paths = File.join('{' + @load_path.join(',') + '}', feature + '{' + SUFFIXES + '}') files = Dir.glob(paths) match = files.find{ |f| ! @loaded_features.include?(f) } return match end |
#require(feature) ⇒ Object
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.
– TODO: Should this be using #include_script instead? ++
127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/capsule.rb', line 127 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 |