Module: Autoload
- Defined in:
- lib/autoload.rb
Overview
Autoload allows you to specify which modules or classes to automatically load when they are referenced. This is somewhat more sophisticated than the autoinclude
mechanism in the standard library. For one thing, you can cause code to be reloaded by using Reloadable in conjunction with Autoload. For another, you can provide a search path using the directories method, thereby allowing you to “autoinclude” entire directories in one fell swoop.
To use Autoload, you must mix it into your module or class via extend. That will provide the autoload and directories methods for you, as described below.
A typical use case for Autoload looks like this:
require 'autocode'
module Models
extend Autoload; extend Reloadable
autoload true; directories :models
end
Class Method Summary collapse
-
.extended(mod) ⇒ Object
:nodoc:.
Class Method Details
.extended(mod) ⇒ Object
:nodoc:
19 20 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 |
# File 'lib/autoload.rb', line 19 def self.extended( mod ) #:nodoc: old = mod.method( :const_missing ) mod..class_eval do # Specifies that you want to autoload each of the constants referenced by keys. A key of true is basically a wild-card, meaning "load anything". def autoload( *keys ) ( @autoload ||= [] ).concat(keys) return self end # Provide a list of directories from which a given constant might be loaded. def directories( *dirs ) ( @directories ||= ['.'] ).concat(dirs) return self end # Is a given constant being autoloaded? def autoload?( cname ) cname = cname.to_s.gsub(/([a-z\d])([A-Z])/){ "#{$1}_#{$2.downcase}"} # is this name autoloadable? key = ( @autoload ||= [] ).find do |key| key == true || ( key.to_s == cname ) end end define_method :const_missing do | cname | #:nodoc: return old.call(cname) unless autoload?( cname ) fname = ( cname.to_s.gsub(/([a-z\d])([A-Z])/){ "#{$1}_#{$2.downcase}"} + '.rb' ).downcase dir = ( @directories ||= ['.'] ).find do |dir| File.exist?( dir / fname ) end if ( dir && load( dir / fname ) && c = const_get( cname ) ) ( @reloadable ||= [] ) << cname; return c else old.call( cname ) end end end end |