Revision 1e8ecd33-fdc5-4fbd-9782-1b044bafba91 - Code Review Stack Exchange

You use eval, but [eval is evil][1].

I tried a solution without eval. For this I used:

* `Module.const_set` to define constants
* `Module.const_defined` to check if a constant is defined
* `Module.const_get` to navigate inside modules
* `Module.new` to define new modules.

My solution (including a little test):

 def def_constants!(hash, context)
 
 #context should be a module. If not, then get (or build) it.
 if context.is_a? String 
 lcontext = Object
 context.split('::').each{ |module_name| 
 lcontext.const_set(module_name, Module.new) unless lcontext.const_defined?(module_name)
 lcontext = lcontext.const_get(module_name)
 }
 context = lcontext
 end
 
 raise ArgumentError unless context.is_a?(Module)
 
 hash.each do |key, value|
 case value
 when Hash
 module_name = key.upcase #fixme -- convert_string_to_camel_case(key)
 def_constants!( hash[key], [context.name, module_name].join('::'))
 when /::/ # explicitly build out this module (since it doesn't exist) so that we can talk about it
 context.const_set(key.upcase, Module.new)
 lmod = context.const_get(key.upcase)
 value.split('::').each{ |module_name| 
 lmod = lmod.const_set(module_name, Module.new )
 }
 else
 # define the given constant
 context.const_set(key.upcase, value)
 end
 end #hash
 end
 
 module AA #define a start
 end

 require 'yaml'
 def_constants!(YAML.load(DATA), AA)
 p AA.constants
 p AA::KEY
 p AA::SAMPLE_MODULE::SOME_KEY
 p AA::KEY_SHOULD_BE_MODULE
 p AA::KEY_SHOULD_BE_MODULE::I
 p AA::KEY_SHOULD_BE_MODULE::I.constants
 p AA::KEY_SHOULD_BE_MODULE::I::Am
 p AA::KEY_SHOULD_BE_MODULE::I::Am::A
 p AA::KEY_SHOULD_BE_MODULE::I::Am::A::Module


 __END__
 key: value
 numeric_data: 3.221
 sample_module:
 some_key: another value
 key_should_be_module: I::Am::A::Module

I haven't tested it for each usecase. I expect problems, when you try to define modules, where you have already constants with the same name.


Some changes, to use it in your code:

* I skipped convert_string_to_camel_case(key) and replaced it with `upcase`
* Your `@project_name` is my initial `context`.
* (and sure: I renamed the method ;-) )

 [1]: http://stackoverflow.com/questions/2571401/why-exactly-is-eval-evil

AltStyle によって変換されたページ (->オリジナル) /