我有以下代码:
code = "def hi; "hi!"; end"
eval code
hi == "hi!" # true
我可以访问方法hi
,因为当它在评估的代码中定义时,它被定义为主对象的方法。
然而,这也意味着被评估的代码可以访问我在它之外定义的东西:
def hi; "hi!"; end
eval "hi == "hi"" # => true
我希望有一个单独的名称空间,我可以在其中运行经过评估的代码;我该怎么做?
我尝试过使用module_eval
并为命名空间使用模块,但我无法让它定义一个方法或类,并在另一个评估中访问它。
您可以评估对象内部的代码,如下所示:
module DSL
def helper_method_to_be_used_by_evaled_code
# ...
end
# ...
end
container = Object.new
container.extend(DSL)
File.open(eval_file1, 'r') {|f| container.instance_eval(f.read, eval_file1)}
File.open(eval_file2, 'r') {|f| container.instance_eval(f.read, eval_file2)}
有了这个,您可以控制是否在eval之间保留定义:您可以重用container
实例,也可以处理它并创建新实例。这将适用于方法定义和常量,在这样的调用之间不会保留局部变量。
此外,您可能希望查看BlankState
模式,而不是Object
。"blankslate"就是一个例子。
您似乎并不是在谈论将模块作为评估代码的一部分,所以这样的东西应该很好:
module EvalMethods
class << self
code = "def hi; "hi!"; end"
eval code
end
end
puts EvalMethods::hi == "hi!"