Class: Hyperloop::Autoloader
Class Method Summary collapse
- .const_missing(const_name, mod) ⇒ Object
- .guess_for_anonymous(const_name) ⇒ Object
- .history ⇒ Object
-
.history=(a) ⇒ Object
All files ever loaded.
- .load_missing_constant(from_mod, const_name) ⇒ Object
- .load_paths ⇒ Object
- .load_paths=(a) ⇒ Object
- .loaded ⇒ Object
- .loaded=(a) ⇒ Object
- .loading ⇒ Object
- .loading=(a) ⇒ Object
- .missing_name?(e, name) ⇒ Boolean
-
.qualified_name_for(mod, name) ⇒ Object
Returns the constant path for the provided parent and constant name.
- .require_or_load(from_mod, module_path) ⇒ Object
- .search_for_module(path) ⇒ Object
-
.to_constant_name(desc) ⇒ Object
Convert the provided const desc to a qualified constant name (as a string).
- .underscore(string) ⇒ Object
Class Method Details
.const_missing(const_name, mod) ⇒ Object
38 39 40 41 42 |
# File 'lib/hyperloop/autoloader.rb', line 38 def self.const_missing(const_name, mod) # name.nil? is testing for anonymous from_mod = mod.name.nil? ? guess_for_anonymous(const_name) : mod load_missing_constant(from_mod, const_name) end |
.guess_for_anonymous(const_name) ⇒ Object
44 45 46 47 48 49 50 |
# File 'lib/hyperloop/autoloader.rb', line 44 def self.guess_for_anonymous(const_name) if Object.const_defined?(const_name) raise NameError.new "#{const_name} cannot be autoloaded from an anonymous class or module", const_name else Object end end |
.history ⇒ Object
9 10 11 |
# File 'lib/hyperloop/autoloader.rb', line 9 def self.history @@history end |
.history=(a) ⇒ Object
All files ever loaded.
6 7 8 |
# File 'lib/hyperloop/autoloader.rb', line 6 def self.history=(a) @@history = a end |
.load_missing_constant(from_mod, const_name) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/hyperloop/autoloader.rb', line 52 def self.load_missing_constant(from_mod, const_name) # see active_support/dependencies.rb in case of reloading on how to handle qualified_name = qualified_name_for(from_mod, const_name) qualified_path = underscore(qualified_name) module_path = search_for_module(qualified_path) if module_path if loading.include?(module_path) raise "Circular dependency detected while autoloading constant #{qualified_name}" else require_or_load(from_mod, module_path) raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{module_path} to define it" unless from_mod.const_defined?(const_name, false) return from_mod.const_get(const_name) end elsif (parent = from_mod.parent) && parent != from_mod && ! from_mod.parents.any? { |p| p.const_defined?(const_name, false) } begin return parent.const_missing(const_name) rescue NameError => e raise unless missing_name?(e, qualified_name_for(parent, const_name)) end end end |
.load_paths ⇒ Object
17 18 19 |
# File 'lib/hyperloop/autoloader.rb', line 17 def self.load_paths @@load_paths end |
.load_paths=(a) ⇒ Object
14 15 16 |
# File 'lib/hyperloop/autoloader.rb', line 14 def self.load_paths=(a) @@load_paths = a end |
.loaded ⇒ Object
25 26 27 |
# File 'lib/hyperloop/autoloader.rb', line 25 def self.loaded @@loaded end |
.loaded=(a) ⇒ Object
22 23 24 |
# File 'lib/hyperloop/autoloader.rb', line 22 def self.loaded=(a) @@loaded = a end |
.loading ⇒ Object
33 34 35 |
# File 'lib/hyperloop/autoloader.rb', line 33 def self.loading @@loading end |
.loading=(a) ⇒ Object
30 31 32 |
# File 'lib/hyperloop/autoloader.rb', line 30 def self.loading=(a) @@loading = a end |
.missing_name?(e, name) ⇒ Boolean
76 77 78 79 80 81 |
# File 'lib/hyperloop/autoloader.rb', line 76 def self.missing_name?(e, name) mn = if /undefined/ !~ e. $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ e. end mn == name end |
.qualified_name_for(mod, name) ⇒ Object
Returns the constant path for the provided parent and constant name.
84 85 86 87 |
# File 'lib/hyperloop/autoloader.rb', line 84 def self.qualified_name_for(mod, name) mod_name = to_constant_name(mod) mod_name == 'Object' ? name.to_s : "#{mod_name}::#{name}" end |
.require_or_load(from_mod, module_path) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/hyperloop/autoloader.rb', line 89 def self.require_or_load(from_mod, module_path) return if loaded.include?(module_path) loaded << module_path loading << module_path begin result = require module_path rescue Exception loaded.delete module_path raise LoadError, "Unable to autoload: require_or_load #{module_path} failed" ensure loading.pop end # Record history *after* loading so first load gets warnings. history << module_path result # end end |
.search_for_module(path) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/hyperloop/autoloader.rb', line 109 def self.search_for_module(path) # oh my! imagine Bart Simpson, writing on the board: # "javascript is not ruby, javascript is not ruby, javascript is not ruby, ..." # then running home, starting irb, on the fly developing a chat client and opening a session with Homer at his workplace: "Hi Dad ..." load_paths.each do |load_path| mod_path = load_path + '/' + path return mod_path if `Opal.modules.hasOwnProperty(#{mod_path})` end return path if `Opal.modules.hasOwnProperty(#{path})` nil # Gee, I sure wish we had first_match ;-) end |
.to_constant_name(desc) ⇒ Object
Convert the provided const desc to a qualified constant name (as a string). A module, class, symbol, or string may be provided.
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/hyperloop/autoloader.rb', line 123 def self.to_constant_name(desc) #:nodoc: case desc when String then desc.sub(/^::/, '') when Symbol then desc.to_s when Module desc.name || raise(ArgumentError, 'Anonymous modules have no name to be referenced by') else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}" end end |
.underscore(string) ⇒ Object
134 135 136 |
# File 'lib/hyperloop/autoloader.rb', line 134 def self.underscore(string) string.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase end |