我的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还没有遇到这个问题,所以现在这已经足够了。