1

我的 Ruby DSL 的用户希望能够添加其他方法并在任意块的上下文中调用它们,例如:

def do_something
  override 'flags', 'ABC'        
end

project('XXX') do
  configuration('debug') do
    do_something
  end
end

在此示例中,“覆盖”是使用 instance_eval 调用的配置对象的方法。

有没有办法强制在配置块的上下文中执行任何方法调用,以便例如可以解决和执行“覆盖”?

[编辑]

所以我构造了根 DSL 对象并评估如下:

root_dsl = DSL.new
root_dsl.instance_eval(File.read(filename))

这个 DSL 类有一个匹配上述示例中的“项目”的方法:

def project(&block) do
    project_dsl = ProjectDSL.new
    project_dsl.instance_eval(&block)
end

并且 project_dsl 类有一个与上面示例中的“配置”匹配的方法:

def configuration(name, &block) do
   configuration_dsl = ProjectConfigDSL.new(name)
   configuration_dsl.instance_eval(&block)
end

等等。用户希望他在 DSL 文件本身中定义的方法在 ProjectConfigDSL 对象的上下文中执行。

4

2 回答 2

0

我在自己的代码中这样做的方式是让辅助函数返回一个传递给 instance_eval 的过程。例如:

def do_something
  Proc.new do
    override 'flags', 'ABC'
  end        
end

project('XXX') do
  configuration 'debug', &do_something
end
于 2017-03-18T20:22:40.863 回答
0

所以我不知道 instance_eval 沙箱的作用域是那个实例,所以我必须做的是从根 DSL 对象委托,直接执行块并将missing_method 中的调用转发给子 DSL 对象,并在整个过程中重复这种模式下。

通过这样做,它修复了范围问题,但它确实导致了一个新的冲突方法名称被转发到错误对象的问题。幸运的是,我的 DSL 还没有遇到这个问题,所以现在这已经足够好了。

于 2017-03-19T07:58:55.483 回答