class Autoloaded::Autoloader

Autoloads files in a source directory.

@since 1.3

Attributes

host_binding[R]

The source code context in which autoloading is to occur.

@return [Binding]

@see autoload!

@api private

specifications[R]

Public Class Methods

new(host_binding) click to toggle source

Constructs a new Autoloader with the specified host_binding.

@param [Binding] host_binding a value for #host_binding

@raise [ArgumentError] host_binding is nil

@api private

# File lib/autoloaded/autoloader.rb, line 30
def initialize(host_binding)
  raise(::ArgumentError, "can't be nil") if host_binding.nil?

  @host_binding = host_binding
  @specifications = Specifications.new
end

Public Instance Methods

autoload!() click to toggle source

Issues autoload statements for source files found in #from. The constants are renamed by #with and #only. The source files are filtered by #except and #only.

@return [Array of Array] the arguments passed to each autoload statement

made

@see ruby-doc.org/core/Module.html#method-i-autoload Module#autoload @see ruby-doc.org/core/Kernel.html#method-i-autoload Kernel#autoload @see from @see except @see only @see with

@api private

# File lib/autoloaded/autoloader.rb, line 52
def autoload!
  result = []
  from_load_pathed_directory.each_source_filename do |source_filename|
    source_basename = ::File.basename(source_filename)
    next if specifications.except.any? { |spec| spec.match source_basename }

    unless specifications.only.empty? ||
           specifications.only.any? { |spec| spec.match source_basename }
      next
    end

    first_match = (specifications.with + specifications.only).inject(nil) do |match, spec|
      match || spec.match(source_basename)
    end
    constant_names = Array(first_match ||
                           Inflection.to_constant_name(source_basename))
    existing_source_filenames = constant_names.collect do |const|
      existing_autoload? const
    end
    if existing_source_filenames.all? { |file| file == source_filename }
      next
    end

    existing_source_filenames.zip(constant_names).each do |file, const|
      if file
        Warning.changing_autoload constant_name:        constant_full_name(const),
                                  old_source_filename:  file,
                                  new_source_filename:  source_filename,
                                  host_source_location: host_source_location
      end
    end

    if existing_source_filenames.compact.empty?
      constant_names.each do |const|
        next unless existing_constant?(const)

        # Don't warn about an existing MyAwesomeGem::VERSION constant since
        # probably it was loaded by a `require 'my_awesome_gem/version'`
        # statement in 'my_awesome_gem.gemspec'.
        next if (const == :VERSION)

        Warning.existing_constant constant_name:        constant_full_name(const),
                                  source_filename:      source_filename,
                                  host_source_location: host_source_location
      end
    end

    constant_names.each do |const|
      establish_autoload const, source_filename
      result << [const, source_filename]
    end
  end
  result
end
from(value=nil) click to toggle source

The directory from which source files are autoloaded.

Defaults to the directory corresponding to the +__FILE__+ of #host_binding. For example, if eval('__FILE__', host_binding) evaluates to +‘/absolute/path/to/my_awesome_gem.rb’+, then the default value of #from is +‘/absolute/path/to/my_awesome_gem’+.

@param [String] value a source directory path; optional

@return [String] if value is nil, the source directory @return [Autoloader] if value is not nil, the Autoloader

@raise [ArgumentError] value is a relative path

@see autoload! @see host_binding

# File lib/autoloaded/autoloader.rb, line 215
def from(value=nil)
  if value.nil?
    return (instance_variable_defined?(:@from) && @from && @from.path) ||
           default_from
  end

  # Validate value.
  @from = LoadPathedDirectory.new(value)

  self
end

Private Instance Methods

constant_full_name(constant_name) click to toggle source
# File lib/autoloaded/autoloader.rb, line 231
def constant_full_name(constant_name)
  "#{host_eval 'name rescue nil'}::#{constant_name}"
end
default_from() click to toggle source
# File lib/autoloaded/autoloader.rb, line 235
def default_from
  filename = host_source_filename
  dirname  = ::File.dirname(filename)
  basename = ::File.basename(filename, ::File.extname(filename))
  ::File.join dirname, basename
end
establish_autoload(constant_name, source_filename) click to toggle source
# File lib/autoloaded/autoloader.rb, line 242
def establish_autoload(constant_name, source_filename)
  host_eval "autoload #{constant_name.to_sym.inspect}, #{source_filename.inspect}"
end
existing_autoload?(constant_name) click to toggle source
# File lib/autoloaded/autoloader.rb, line 246
def existing_autoload?(constant_name)
  host_eval "autoload? #{constant_name.to_sym.inspect}"
end
existing_constant?(constant_name) click to toggle source
# File lib/autoloaded/autoloader.rb, line 250
def existing_constant?(constant_name)
  host_eval "constants.include? #{constant_name.to_sym.inspect}"
end
from_load_pathed_directory() click to toggle source
# File lib/autoloaded/autoloader.rb, line 254
def from_load_pathed_directory
  (instance_variable_defined?(:@from) && @from) ||
    LoadPathedDirectory.new(default_from)
end
host_eval(statement) click to toggle source
# File lib/autoloaded/autoloader.rb, line 259
def host_eval(statement)
  # TODO: Why does adding the third and fourth arguments break Kernel#eval ?
  # ::Kernel.eval statement, host_binding, __FILE__, __LINE__
  ::Kernel.eval statement, host_binding
end
host_source_filename() click to toggle source
# File lib/autoloaded/autoloader.rb, line 265
def host_source_filename
  if host_binding.respond_to?(:source_location)
    host_eval "::File.expand_path '#{host_binding.source_location.first}'"
  else
    host_eval '::File.expand_path __FILE__'
  end
end
host_source_location() click to toggle source
# File lib/autoloaded/autoloader.rb, line 273
def host_source_location
  if host_binding.respond_to?(:source_location)
    host_binding.source_location
  else
    host_eval('[__FILE__, __LINE__]')
  end.collect(&:to_s).join ':'
end