我的Ruby DSL的用户希望能够添加其他方法并在任意块的上下文中调用它们,例如:
def do_something
override 'flags', 'ABC'
end
project('XXX') do
configuration('debug') do
do_something
end
end
在此示例中,'override'是使用instance_eval调用的配置对象的方法。
是否有办法强制在配置块的上下文中执行任何方法调用,以便例如可以解析并执行'override'?
[编辑]
所以我构造了根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类有一个匹配上面例子中'configuration'的方法:
def configuration(name, &block) do
configuration_dsl = ProjectConfigDSL.new(name)
configuration_dsl.instance_eval(&block)
end
等等。用户希望他在DSL文件中定义的方法本身在ProjectConfigDSL对象的上下文中执行。
答案 0 :(得分:0)
我在自己的代码中执行此操作的方法是使辅助函数返回一个传递给instance_eval的proc。例如:
def do_something
Proc.new do
override 'flags', 'ABC'
end
end
project('XXX') do
configuration 'debug', &do_something
end
答案 1 :(得分:0)
所以我不知道instance_eval沙箱是该实例的范围,所以我必须做的是直接执行块从根DSL对象委托并将missing_method中的调用转发到子DSL对象,并重复此模式整个下来。
通过执行此操作可以修复范围问题,但它确实会导致新的collliding方法名称被转发到错误的对象。幸运的是我的DSL尚未遇到这个问题,所以现在这已经足够了。