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
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
|
# File 'lib/autocode.rb', line 19
def self.included( mod )
mod.instance_eval do
return unless @autocode.nil?
@autocode = {
:constructors => Hash.new { |h,k| h[k] = [] },
:initializers => Hash.new { |h,k| h[k] = [] },
:loaded => []
}
def auto_create( key = true, options = {}, &block )
@autocode[:constructors][ AutoCode.normalize( key ) ] << lambda do | cname |
exemplar = ( options[:exemplar] || Module.new ).clone
exemplar.module_eval( &block ) if block
const_set( cname, exemplar ) and true
end
end
def auto_load( key = true, options = {} )
@autocode[:constructors][ AutoCode.normalize( key ) ] << lambda do | cname |
filename = AutoCode.snake_case( cname ) << '.rb'
options[:directories] ||= '.'
path = options[:directories].
map { |dir| File.join( dir.to_s, filename ) }.
find { |path| File.exist?( path ) }
Kernel.load( path ) unless path.nil?
end
end
def auto_eval( key, &block )
@autocode[:initializers][ AutoCode.normalize( key ) ] << lambda do | mod |
mod.module_eval( &block )
end
end
def auto_create_class( key = true, superclass = Object, &block )
auto_create( key,{ :exemplar => Class.new( superclass ) }, &block )
end
def auto_create_module( key = true, &block )
auto_create( key,{ :exemplar => Module.new }, &block )
end
def reloadable ; @autocode[:loaded] ; end
def reload ; @autocode[:loaded].each { |name| remove_const( name ) } ; @autocode[:loaded] = [] ; end
private
old = method( :const_missing )
(class << self ; self ; end ).instance_eval do
define_method( :const_missing ) do | cname |
constructors = @autocode[:constructors][true] + @autocode[:constructors][cname]
constructors.reverse.find { | c | c.call( cname ) and const_defined?( cname ) }
return old.call( cname ) unless const_defined?( cname )
initializers = @autocode[:initializers][true] + @autocode[:initializers][cname]
mod = const_get( cname ); initializers.each { |init| init.call( mod ) }
@autocode[:loaded] << cname
mod
end
end
end
end
|