From: Joel VanderWerf Date: 2005-02-20T17:32:05+09:00 Subject: Re: Why don't I see these module constants? Lloyd Zusman wrote: > Suppose I have a file named 'modtest' which contains the following two > lines: > > X = 1 > Y = 2 > > Then, I execute this ruby code: > > mod = Module.new { > load('modtest') > } > p mod.constants > > When this code runs, I see this: [] > > In other words, it's an empty array, which means that I'm not seeing the > constants X and Y. > > Why is this? Is there any way to load the file 'modtest' so that the > resulting anonymous module indeed contains these constants? It's not particularly loading that's causing the problem. The same behavior occurs in mod = Module.new { XYZ = 1 } p mod.constants We can find out where that constant goes with this bit of code: ObjectSpace.each_object(Module) do |obj| if obj.constants.include?("XYZ") puts "#{obj}::XYZ = #{obj::XYZ.inspect}" end end The output: [] t.rb:8: warning: toplevel constant XYZ referenced by Class::XYZ Class::XYZ = 1 t.rb:8: warning: toplevel constant XYZ referenced by Module::XYZ Module::XYZ = 1 Object::XYZ = 1 The output says XYZ is toplevel. The constant is added in the top level scope because that is the scope of the block in which the constant assignment happens. Here's another example: module Foo; end module Bar $block = proc { XYZ = 1 } end Foo.module_eval(&$block) p Bar::XYZ # ==> 1 p Foo::XYZ # ==> uninitialized constant Looks weird at first, but it's because constants are statically (lexically) scoped. XYZ occurs in a block whose scope is Bar, so that's where the constant is defined when the block is called. You can get around this by using the string form of module_eval. A string is not associated with its lexical scope in the way a proc is. mod2 = Module.new mod2.module_eval "X2 = 12" p mod2.constants # ==> ["X2"] So just use #read instead of #load, and pass that string to module_eval.