Sometimes we want to define modules using String
and instance_eval
.
class A
end
code = <<-CODE
module B
module_function
def b
puts 'b'
end
end
CODE
a = A.new
a.instance_eval code
B.b # => Should print 'b'
However, this code causes NameError
saying uninitialized constant B
.
Where has it gone? To know where module B is defined, we use ObjectSpace
class.
# Replace `B.b` in the snippet above with this
ObjectSpace.each_object(Module) {|m| p m if m.name =~ /::B/ }
# => You see something like "#<Class:0x00007f861b8c8e50>::B"
OK, with instance_eval
and String combination, the defined module is put in Anonymous class namespace, the way which we don't like. How to define a toplevel module with instance_eval
?
So here's the answer.
class A
end
code = <<-CODE
module B
module_function
def b
puts 'b'
end
end
CODE
a = A.new
a.instance_eval do
eval code
end
B.b # => "b" is printed
What happened? We eval code
string in instance_eval
block. I don't know why but this code just does what we want to do.
Top comments (0)