module Truck class Context attr :autoload_paths, :name, :root def initialize(name, root, parent, autoload_paths) @name = name @root = Pathname(root) @parent = parent @autoload_paths = expand_autoload_paths autoload_paths end class << self def owner(const) owner, _ = Autoloader.owner_and_ascending_nibbles const owner end end def boot! parent.const_set name, build_mod end def mod return nil unless parent and parent.const_defined? name parent.const_get name end def context_for?(other_mod) mod == other_mod or other_mod.included_modules.include? mod end def booted? mod ? true : false end def eager_load! Dir[root.join('**/*.rb')].each do |rb_file| load_file rb_file end end def load_file(rb_file) ruby_code = File.read rb_file mod.module_eval ruby_code, rb_file.to_s end def parent return Object unless @parent Truck.contexts.fetch(@parent.to_sym).mod end def resolve_const(expanded_const, skip = nil) build_const_resolver(expanded_const, Array[skip]).resolve end def shutdown! parent.send :remove_const, name end private def build_const_resolver(expanded_const, skip_files) ConstResolver.new self, String(expanded_const).dup.freeze, skip_files end def build_mod mod = Module.new mod.singleton_class.class_exec root do |__root__| define_method :root do __root__ ; end end mod end def expand_autoload_paths(paths) paths.map do |path| root.join path; end end end class AutoloadError < NameError attr :const, :rb_file def initialize(const, rb_file) @const = const @rb_file = rb_file end def message "Expected #{rb_file} to define #{const}" end end end