Forum: Ruby Requiring a file into a different namespace

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2b1b2c4661dd593b46ecd24492bc243d?d=identicon&s=25 Michael Judge (bluetrust)
on 2006-06-07 23:19
  ["a","b"].each do |name|
    sandbox = Module.new { require "#{name}.rb" }

    survey = sandbox::Survey.new

    puts survey.name
  end

This is what I'd like to do, but 'name' is out of scope and when I
hardcode it, it seems like require is pulling class Survey from the file
into the global namespace rather than the anonymous module's namespace.
It's weird.

Anyone have a solution for requiring a file into a different namespace?
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-06-07 23:46
(Received via mailing list)
On Jun 7, 2006, at 5:19 PM, Michael Judge wrote:

> hardcode it, it seems like require is pulling class Survey from the
>
Search the mailing list archives, this was discussed very recently.
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-06-08 01:53
(Received via mailing list)
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
0b561a629b87f0bbf71b45ee5a48febb?d=identicon&s=25 Dave Burt (Guest)
on 2006-06-08 04:10
(Received via mailing list)
Michael Judge wrote:
> hardcode it, it seems like require is pulling class Survey from the file
> into the global namespace rather than the anonymous module's namespace.
> It's weird.

It's not weird. Require (or load) is going to load the script normally
and return true or false; that line is (except for order of execution)
the same as this:

x = require "#{name}.rb"
sandbox = Module.new { x }

If what you want is for the script's code to be evaluated in the
context of the module, you need to use module_eval, as seen in the
latest ruby-dev summary:

sandbox = Module.new
sandbox.module_eval File.read("#{name}.rb")

Cheers,
Dave
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-06-08 19:22
(Received via mailing list)
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

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
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-06-08 19:58
(Received via mailing list)
Jacob Fugal wrote:
>
> Unfortunately, this won't work. You can't even do this directly:

Ah crud. I actually meant:

  module_eval File.read("#{name}.rb")

(I've made that booboo twice now!) Sorry about that.

T.
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-06-08 20:02
(Received via mailing list)
Jacob Fugal wrote:

>
> How do these ideas sound to people?

Sounds good. Although I think the most recent develpoment "trial" is
#require_into.

T.
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-06-09 04:05
(Received via mailing list)
Jacob Fugal wrote:
...
> always true (failure results in an exception), so there should be no
> code relying on the current return value.

Until then, http://raa.ruby-lang.org/project/script may be useful.
This topic is locked and can not be replied to.