Module: Autocode
- Defined in:
- lib/autocode.rb
Class Method Summary collapse
-
.extended(mod) ⇒ Object
:nodoc:.
Class Method Details
.extended(mod) ⇒ Object
:nodoc:
5 6 7 8 9 10 11 12 13 14 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/autocode.rb', line 5 def self.extended( mod ) #:nodoc: old = mod.method( :const_missing ) mod..class_eval do def autocreate( key, exemplar, &block ) keys = case key when true, Symbol then [key] when Array then key end keys.each do |k| exemplars[k] = exemplar init_blocks[k] << block end return self end def autoinit( key, &block ) # See whether we're dealing with a namespaced constant, # The match groupings for, e.g. "X::Y::Z", would be # ["X::Y", "Z"] match = key.to_s.match(/^(.*)::([\w\d_]+)$/) if match namespace, cname = match[1,2] const = module_eval(namespace) const.module_eval do @init_blocks ||= Hash.new { |h,k| h[k] = [] } @init_blocks[cname.to_sym] << block end else @init_blocks ||= Hash.new { |h,k| h[k] = [] } @init_blocks[key] << block end return self end def autoload( key, ) # look for load_files in either a specified directory, or in the directory # with the snakecase name of the enclosing module directories = [[:directories] || default_directory(self.name)].flatten # create a lambda that looks for a file to load file_finder = lambda do |cname| filename = default_file_name(cname) dirname = directories.find do |dir| File.exist?(File.join(dir.to_s, filename)) end dirname ? File.join(dirname.to_s, filename) : nil end # if no exemplar is given, assume Module.new load_files[key] = [file_finder, [:exemplar] || Module.new] return self end def autoload_class(key, superclass=nil, ={}) [:exemplar] = Class.new(superclass) autoload key, end define_method :const_missing do | cname | #:nodoc: cname = cname.to_sym exemplar = exemplars[cname] || exemplars[true] blocks = init_blocks[cname] blocks = init_blocks[true] + blocks if exemplars[cname].nil? && init_blocks[true] load_file_finder, load_class = load_files[cname] || load_files[true] if load_file_finder && filename = load_file_finder.call(cname) object = load_class.clone elsif exemplar object = exemplar.clone else return old.call(cname) end (@reloadable ||= []) << cname; const_set( cname, object ) blocks.each do |block| object.module_eval( &block) if block end load(filename) if filename return object end # helper methods. May need to make them private. def exemplars @exemplars ||= Hash.new end def init_blocks @init_blocks ||= Hash.new { |h,k| h[k] = [] } end def load_files @load_files ||= Hash.new end def reloadable @reloadable ||= [] end def default_file_name(cname) ( cname.to_s.gsub(/([a-z\d])([A-Z\d])/){ "#{$1}_#{$2}"} << ".rb" ).downcase end def default_directory(module_name) m = self.name.match( /^.*::([\w\d_]+)$/) m[1].snake_case end end end |