3

我有以下代码:

code = "def hi; \"hi!\"; end"
eval code

hi == "hi!" # true

我可以访问 method hi,因为在评估代码中定义它时,它被定义为主对象的方法。

然而,这也意味着被评估的代码可以访问我在它之外定义的东西:

def hi; "hi!"; end
eval "hi == \"hi\"" # => true

我想有一个单独的命名空间,我可以在其中运行评估代码;我该怎么做?

我尝试使用module_eval和使用命名空间的模块,但我无法让它定义一个方法或一个类并在另一个评估中访问它。

4

2 回答 2

3

您可以像这样评估对象内部的代码:

  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实例或处置它并创建新实例。这适用于方法定义和常量,在此类调用之间不保留局部变量。

此外,Object您可能想要查看BlankState模式,而不是。“ blankslate ”就是一个例子。

于 2012-08-26T17:27:10.433 回答
0

您似乎不是在谈论使模块成为评估代码的一部分,所以这样的事情应该可以正常工作:

module EvalMethods
  class << self
    code = "def hi; \"hi!\"; end"
    eval code
  end
end

puts EvalMethods::hi == "hi!"
于 2012-08-26T17:00:55.950 回答