Ruby DSL - 在块上下文中调用用户提供的方法



我的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类有一个与上面示例中的"project"匹配的方法:

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 对象的上下文中执行。

我在自己的代码中执行此操作的方法是使帮助程序函数返回传递给instance_eval的进程。 例如:

def do_something
  Proc.new do
    override 'flags', 'ABC'
  end        
end
project('XXX') do
  configuration 'debug', &do_something
end

所以我不知道instance_eval沙箱的范围到该实例,所以我必须做的是从根 DSL 对象委派,直接执行块并将missing_method中的调用转发到子 DSL 对象,并一直重复此模式。

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

最新更新