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

时间:2017-03-18 10:12:14

标签: ruby instance-eval

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

2 个答案:

答案 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尚未遇到这个问题,所以现在这已经足够了。