Method: ClassLoader.load
- Defined in:
- lib/class_loader/class_loader.rb
.load(namespace, const) ⇒ Object
Hierarchically searching for class file, according to modules hierarchy.
For example, let’s suppose that C class defined in ‘/lib/a/c.rb’ file, and we referencing it in the A::B namespace, like this - A::B::C, the following files will be checked:
-
‘/lib/a/b/c.rb’ - there’s nothing, moving up in hierarchy.
-
‘/lib/a/c.rb’ - got and load it.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/class_loader/class_loader.rb', line 21 def load namespace, const monitor.synchronize do original_namespace = namespace namespace = nil if namespace == Object or namespace == Module target_namespace = namespace # Need this hack to work with anonymous classes. namespace = eval "#{name_hack(namespace)}" if namespace # Hierarchically searching for class name. hierarchy = {} begin class_name = namespace ? "#{namespace.name}::#{const}" : const.to_s class_file_name = get_file_name class_name binding = namespace || Object hierarchy[class_file_name] = binding # Skip some constants. return nil if SKIP.any?{|c| class_name == c or class_name.include?("#{c}::")} # Trying to load class file, if its exist. loaded = begin require class_file_name true rescue LoadError => e # Not the best way - hardcoding error messages, but it's the fastest way # to check existence of file & load it. unless e. =~ /no such file.*#{Regexp.escape(class_file_name)}/ raise e.class, e., filter_backtrace(e.backtrace) end false end if loaded # Checking that class hasn't been loaded previously, sometimes it may be caused by # weird class definition code. if loaded_classes.include? class_name msg = "something wrong with '#{const}' referenced from '#{original_namespace}' scope!" raise NameError, msg, filter_backtrace(caller) end # Checking that class defined in correct namespace, not the another one. unless binding.const_defined? const, false msg = "class name #{class_name} doesn't correspond to file name '#{class_file_name}'!" raise NameError, msg, filter_backtrace(caller) end # Getting the class itself. klass = binding.const_get const, false # Firing after callbacks. if callbacks = after_callbacks[klass.name] then callbacks.each{|c| c.call klass} end loaded_classes[class_name] = klass return klass end # Moving to higher namespace. global_also_tried = namespace == nil namespace = Module.namespace_for namespace.name if namespace end until global_also_tried # If file not found trying to find directory and evaluate it as a module. hierarchy.each do |path, binding| $LOAD_PATH.each do |base| next unless File.directory? File.join(base, path) amodule = Module.new binding.const_set const, amodule return amodule end end return nil end end |