Unfortunately, this won't work. You can't even do this directly:
$ cat a.rb
sandbox = Module.new{ module Survey; end }
p sandbox::Survey rescue puts "sandbox has no Survey"
p Survey rescue puts "there is no top level Survey"
$ ruby a.rb
sandbox has no Survey
Survey
So, you can see, the Survey module is defined at the top level, rather
than inside the anonymous sandbox. The same thing happens for
module_eval, instance_eval and class_eval in block form. However, in
string form, module_eval does the trick:
$ cat b.rb
sandbox = Module.new
sandbox.module_eval "module Survey; end"
p sandbox::Survey rescue puts "sandbox has no Survey"
p Survey rescue puts "there is no top level Survey"
$ ruby b.rb
#<Module:0x402a3cc0>::Survey
there is no top level Survey
This is simply enough extended for getting the string to be eval'd via
File.read:
$ cat source.rb
module Survey; end
$ cat target.rb
sandbox = Module.new
sandbox.module_eval File.read("source.rb")
p sandbox::Survey rescue puts "sandbox has no Survey"
p Survey rescue puts "there is no top level Survey"
$ ruby target.rb
#<Module:0x402a3bf8>::Survey
there is no top level Survey
What I really want to know is this: Kernel#load allows a parameter
that wraps the loaded file in an anonymous module, so as not to
pollute the global namespace. But that anonymous module is discarded
-- as far as I can tell, the only use for this style of load is if the
only portion of the file you're interested in is the side effects.
I suggest one of two changes.
1) Change Kernel#load to return the anonymous module when the wrap
parameter is true. Currently, the return value of Kernel#load is
always true (failure results in an exception), so there should be no
code relying on the current return value.
2) Since the wrap parameter can only be true or false right now,
change that parameter to accept a module. The behavior when that
parameter is false/nil/true is unchanged for backwards compatibility,
but if the parameter is a module, load the file into that module
instead of into a new anonymous module.
How do these ideas sound to people?
Jacob Fugal
···
On 6/7/06, transfire@gmail.com <transfire@gmail.com> wrote:
Use #load. Not tested but it will be something like:
["a","b"].each do |name|
sandbox = Module.new { load "#{name}.rb" }
survey = sandbox::Survey.new
puts survey.name
end