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

Ruby DSL—在块上下文中调用用户提供的方法,ruby,instance-eval,Ruby,Instance Eval,我的Ruby DSL用户希望能够添加其他方法,并在任意块的上下文中调用它们,例如: def do_something override 'flags', 'ABC' end project('XXX') do configuration('debug') do do_something end end def do_something Proc.new do override 'flags', 'ABC' end end

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

def do_something
  override 'flags', 'ABC'        
end

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

project('XXX') do
  configuration 'debug', &do_something
end
在这个示例中,“override”是一个配置对象的方法,它通过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对象的上下文中执行。

我在自己的代码中执行此操作的方式是使helper函数返回一个传递给instance_eval的过程。例如:

def do_something
  override 'flags', 'ABC'        
end

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

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

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

def do_something
  override 'flags', 'ABC'        
end

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

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

所以我不知道instance_eval沙盒的作用域是那个实例,所以我要做的是从根DSL对象委托直接执行块,并将missing_方法中的调用转发给子DSL对象,然后一直重复这个模式


通过这样做,它修复了作用域问题,但它确实导致了一个新的问题,即collliding方法名称被转发到错误的对象。幸运的是,我的DSL还没有遇到这个问题,所以现在这就足够了。

所以我不知道实例\u eval沙盒作用于该实例,所以我必须做的是从根DSL对象委托直接执行块,并将缺少的\u方法中的调用转发给子DSL对象,然后一直重复这个模式


通过这样做,它修复了作用域问题,但它确实导致了一个新的问题,即collliding方法名称被转发到错误的对象。幸运的是,我的DSL还没有遇到这个问题,所以这就足够了。

您介意分享DSL实现本身吗?@mudasobwa我已按要求添加了更多的实现细节您介意分享DSL实现本身吗?@mudasobwa我已按要求添加了更多的实现细节