Module: Loadable
- Included in:
- GemLoader, OriginalLoader, RollLoader, RubyLoader, VendorLoader
- Defined in:
- lib/loadable/mixin.rb,
lib/loadable/domain.rb,
lib/loadable/loaders/gem_loader.rb,
lib/loadable/loaders/roll_loader.rb,
lib/loadable/loaders/ruby_loader.rb,
lib/loadable/loaders/vendor_loader.rb,
lib/loadable/loaders/original_loader.rb
Overview
First, it can be used as a mixin for loaders (also called load wedges). Loaders are used to safely inject new import logic into Ruby’s require/load system.
Secondly, Loadable’s class methods are used to override Ruby’s built-in require and load Kernel methods.
Active load wedges are stored in ‘$LOADERS` global variable.
IMPORTANT: This must be loaded before ‘loadable/kernel.rb`.
Defined Under Namespace
Classes: GemLoader, OriginalLoader, RollLoader, RubyLoader, VendorLoader
Constant Summary collapse
- RB_EXTS =
Script extensions recognized by Ruby (MRI and variants).
['.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
Class Method Summary collapse
-
.call(fname, options = {}) ⇒ Object
Require/load script.
-
.each(options = {}, &block) ⇒ Object
Iterate over all requirable files.
-
.register(loader) ⇒ Object
Add a loader to the $LOADERS global variable.
-
.search(glob, options = {}, &criteria) ⇒ Object
Search wedges for all matching paths.
-
.vendor(*directory) ⇒ Object
Vendor location.
Instance Method Summary collapse
- #call(fname, options = {}) ⇒ Object
-
#default_file_extensions ⇒ Object
private
This method is used by ‘#lookup` to handle defualt file extensions.
-
#each(options = {}, &block) ⇒ Object
A load wedge should provide a means for iterating over all requirable files that its ‘#call` method could load.
-
#lookup(base_path, relative_path, options = {}) ⇒ Object
private
Given a base-path, and a path relative to it determine if a matching file exists.
-
#name ⇒ Object
Name of wedge.
-
#raise_load_error(fname) ⇒ Object
private
Raise LoadError with an error message patterned after Ruby’s standard error message when a script can’t be required or loaded.
-
#traverse(dir, base = dir, &block) ⇒ Object
private
This helper method provides a fast way to traverse a directory recursively iteratating over each file.
Class Method Details
.call(fname, options = {}) ⇒ Object
Require/load script.
11 12 13 14 15 16 17 18 |
# File 'lib/loadable/domain.rb', line 11 def self.call(fname, ={}) success = nil $LOADERS.each do |wedge| success = wedge.call(fname, ) break unless success.nil? end return success end |
.each(options = {}, &block) ⇒ Object
Iterate over all requirable files.
Loadable.each{ |file| p file }
Note that esoteric load wedges may return a symbolic path rather than an actual file path.
27 28 29 30 31 |
# File 'lib/loadable/domain.rb', line 27 def self.each(={}, &block) $LOADERS.each do |wedge| wedge.each(, &block) end end |
.register(loader) ⇒ Object
Add a loader to the $LOADERS global variable.
60 61 62 |
# File 'lib/loadable/domain.rb', line 60 def self.register(loader) $LOADERS.unshift(loader) end |
.search(glob, options = {}, &criteria) ⇒ Object
Search wedges for all matching paths.
Loadable.search('detroit-*.rb')
Note that “esoteric” wedges might return a symbolic identifier rather than an actual file path.
TODO: Handle default ruby extensions in search.
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/loadable/domain.rb', line 41 def self.search(glob, ={}, &criteria) matches = [] $LOADERS.each do |wedge| wedge.each do |path| next unless criteria.call(path) if criteria matches << path if File.fnmatch?(glob, path.to_s) # TODO: add `options[:flags].to_i` ? end end matches end |
.vendor(*directory) ⇒ Object
Vendor location.
54 55 56 |
# File 'lib/loadable/domain.rb', line 54 def self.vendor(*directory) $LOADERS.unshift(VendorLoader.new(*directory)) end |
Instance Method Details
#call(fname, options = {}) ⇒ Object
25 26 27 28 29 30 31 |
# File 'lib/loadable/mixin.rb', line 25 def call(fname, ={}) if [:load] load(fname, [:wrap]) else require(fname) end end |
#default_file_extensions ⇒ Object (private)
This method is used by ‘#lookup` to handle defualt file extensions. By default it returns the value of the `RB_EXTS` constant.
89 90 91 |
# File 'lib/loadable/mixin.rb', line 89 def default_file_extensions RB_EXTS end |
#each(options = {}, &block) ⇒ Object
A load wedge should provide a means for iterating over all requirable files that its ‘#call` method could load.
If a load wedge is “esoteric”, in that it doesn’t actually load a file, then it’s ‘#each` method can iterate over a list of suitable symbolic identifiers, or if otherwise necessary nothing at all. But be sure to document this prominantly!!!
41 42 |
# File 'lib/loadable/mixin.rb', line 41 def each(={}, &block) end |
#lookup(base_path, relative_path, options = {}) ⇒ Object (private)
Given a base-path, and a path relative to it determine if a matching file exists. Unless :load
option is true
, this will check for each viable Ruby suffix. If a match is found the full path to the file is returned, otherwise nil
.
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/loadable/mixin.rb', line 56 def lookup(base_path, relative_path, ={}) exts = default_file_extensions if [:load] or exts.include?(File.extname(relative_path)) abspath = File.join(base_path, relative_path) File.exist?(abspath) ? abspath : nil else exts.each do |ext| abspath = File.join(base_path, relative_path + ext) return abspath if File.exist?(abspath) end nil end end |
#name ⇒ Object
Name of wedge. By default it is simply the class name.
45 46 47 |
# File 'lib/loadable/mixin.rb', line 45 def name self.class.name end |
#raise_load_error(fname) ⇒ Object (private)
Raise LoadError with an error message patterned after Ruby’s standard error message when a script can’t be required or loaded.
96 97 98 |
# File 'lib/loadable/mixin.rb', line 96 def raise_load_error(fname) raise LoadError, "no such file to load -- #{fname}" end |
#traverse(dir, base = dir, &block) ⇒ Object (private)
This helper method provides a fast way to traverse a directory recursively iteratating over each file.
73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/loadable/mixin.rb', line 73 def traverse(dir, base=dir, &block) return unless File.directory?(dir) Dir.new(dir).each do |file| next if file == '.' or file == '..' path = File.join(dir, file) if File.directory?(path) traverse(path, base, &block) else block.call(path.sub(base+'/','')) end end end |