load_missing_constant(from_mod, const_name)
public
Load the constant named const_name which is missing from
from_mod. If it is not possible to load the constant into
from_mod, try its parent module using const_missing.
Show source
def load_missing_constant(from_mod, const_name)
log_call from_mod, const_name
if from_mod == Kernel
if ::Object.const_defined?(const_name)
log "Returning Object::#{const_name} for Kernel::#{const_name}"
return ::Object.const_get(const_name)
else
log "Substituting Object for Kernel"
from_mod = Object
end
end
from_mod = Object if from_mod.name.blank?
unless qualified_const_defined?(from_mod.name) && from_mod.name.constantize.object_id == from_mod.object_id
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
end
raise ArgumentError, "#{from_mod} is not missing constant #{const_name}!" if uninherited_const_defined?(from_mod, const_name)
qualified_name = qualified_name_for from_mod, const_name
path_suffix = qualified_name.underscore
name_error = NameError.new("uninitialized constant #{qualified_name}")
file_path = search_for_file(path_suffix)
if file_path && ! loaded.include?(File.expand_path(file_path))
require_or_load file_path
raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless uninherited_const_defined?(from_mod, const_name)
return from_mod.const_get(const_name)
elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
return mod
elsif (parent = from_mod.parent) && parent != from_mod &&
! from_mod.parents.any? { |p| uninherited_const_defined?(p, const_name) }
begin
return parent.const_missing(const_name)
rescue NameError => e
raise unless e.missing_name? qualified_name_for(parent, const_name)
raise name_error
end
else
raise name_error
end
end