15
16
17
18
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
|
# File 'lib/autocode.rb', line 15
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 )
end
end
def auto_load( key = true, options = {} )
@autocode[:constructors][ AutoCode.normalize( key ) ] << lambda do | cname |
filename = AutoCode.snake_case( cname ) << '.rb'
if options[:directories].nil?
Kernel.load( filename ) if File.exist?( filename )
else
path = options[:directories].
map { |dir| File.join( dir.to_s, filename ) }.
find { |path| File.exist?( path ) }
Kernel.load( path ) unless path.nil?
end
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.pop.call( cname ) until ( const_defined?( cname ) or constructors.empty? )
return old.call( cname ) unless const_defined?( cname )
initializers = @autocode[:initializers][true] + @autocode[:initializers][cname]
mod = const_get( cname ) ; initializers.pop.call( mod ) until initializers.empty?
@autocode[:loaded] << cname ; const_get( cname )
end
end
end
end
|