Hagbard Celine wrote:
Hey folks!
In my current project I try to load a module dynamically. Which is
basically no problem due to 'require` accepting filenames as well. My
problem is that I'd totally pollute my namespace. I thought of something
like the following:
def load_module(filename)
module NamespaceGuard # Just a random name
require filename
# Take a care of the loaded module
end
# My namespace is clean again
end
But Ruby's syntax apparently forbids module definitions in methods. I'd
be very glad if anyone could help me with this problem.
You certainly can define modules dynamically:
def make_mod
Module.new do
def self.foo; p "FOO"; end
def bar; p "BAR"; end
end
end
m = make_mod
p m.methods(false) # ==> ["foo"]
p m.instance_methods(false) # ==> ["bar"]
m.foo # ==> "FOO"
x=
x.extend m
x.bar # ==> "BAR"
Also, the #load method takes an optional argument that causes it to wrap the loaded definitions in
$ ri Kernel#load | cat
------------------------------------------------------------ Kernel#load
load(filename, wrap=false) => true
···
------------------------------------------------------------------------
Loads and executes the Ruby program in the file filename. If the
filename does not resolve to an absolute path, the file is
searched for in the library directories listed in $:. If the
optional wrap parameter is true, the loaded script will be
executed under an anonymous module, protecting the calling
program's global namespace. In no circumstance will any local
variables in the loaded file be propagated to the loading
environment.
You can use this like so:
$ cat b.rb
def foo
puts "foo in b"
end
$ cat a.rb
load "b.rb", true # try this without the true
begin
foo
rescue => e
puts e
end
def foo
puts "foo in a"
end
foo
$ ruby a.rb
undefined local variable or method `foo' for main:Object
foo in a
However, you don't get easy access to the anonymous module. If you want that, I have a little library that may be helpful:
http://redshift.sourceforge.net/script/