Module: AutoCode

Defined in:
lib/autocode.rb

Defined Under Namespace

Classes: Creator, Initializer, Loader

Class Method Summary collapse

Class Method Details

.extended(mod) ⇒ Object



37
# File 'lib/autocode.rb', line 37

def self.extended( mod ) ; included(mod) ; end

.included(mod) ⇒ Object



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
97
98
99
100
101
102
103
# File 'lib/autocode.rb', line 39

def self.included( mod )
  
  mod.instance_eval do

    # Initialize bookkeeping variables needed by AutoCode
    @initializers ||= Hash.new { |h,k| h[k] = [] }; @reloadable ||= []
    
    # Adds an auto_create block for the given key using the given exemplar if provided
    def auto_create( key = true, options = {}, &block )
      @initializers[ AutoCode.normalize( key ) ] << Creator.new( options, &block ); self
    end

    # Adds an auto_load block for the given key and directories
    def auto_load( key = true, options = {} )
      @initializers[ AutoCode.normalize( key ) ].unshift( Loader.new( options ) ); self
    end

    # Adds an arbitrary initializer block for the given key
    def auto_eval( key, &block )
      @initializers[ AutoCode.normalize( key ) ] << Initializer.new( &block ); self
    end

    # Convenience method for auto_create.
    def auto_create_class( key = true, superclass = Object, &block )
      auto_create( key,{ :exemplar => Class.new( superclass ) }, &block )
    end

    # Convenience method for auto_create.
    def auto_create_module( key = true, &block )
      auto_create( key,{ :exemplar => Module.new }, &block )
    end

    # Reloading stuff ...
    
    # Returns the list of constants that would be reloaded upon a call to reload.
    def reloadable( *names ) ; @reloadable + names ; end

    # Reloads all the constants that were loaded via auto_code. Technically, all reload
    # is doing is undefining them (by calling +remove_const+ on each in turn); they won't get
    # reloaded until they are referenced.
    def reload ; @reloadable.each { |name| remove_const( name ) } ; @reloadable = [] ; self; end

    # Unloads all the constants that were loaded and removes all auto* definitions.
    def unload ; reload ; @initializers = Hash.new { |h,k| h[k] = [] } ; self ; end

    private

    old = method( :const_missing )
    (class << self ; self ; end ).instance_eval do
      define_method :const_missing do | cname |
        ( @initializers[cname] + @initializers[true] ).each do |initializer|
          case initializer 
          when Loader then initializer.call( cname ) unless const_defined?(cname)
          when Creator then const_set( cname, initializer.call ) unless const_defined?(cname)
          else
            return old.call(cname) unless const_defined?( cname )
            initializer.call( const_get( cname ) ) if const_defined?( cname )
          end
        end
        return old.call(cname) unless const_defined?( cname )
        @reloadable << cname ; const_get( cname )
      end
    end
  end
end

.normalize(cname) ⇒ Object

always make sure we have a camel-cased symbol



4
5
6
7
# File 'lib/autocode.rb', line 4

def AutoCode.normalize( cname )  
  return cname unless cname.is_a? String
  cname.gsub(/(_)(\w)/) { $2.upcase }.gsub(/^([a-z])/) { $1.upcase }.intern
end