Ruby - 如何拦截块并在评估或修改之前对其进行修改?

时间:2015-01-20 21:03:54

标签: ruby

我一直在考虑Ruby中的块。

请考虑以下代码:

div {
  h2 'Hello world!'
  drag
}

调用方法div(),并将块传递给它。

有了收益率,我可以评估该块。

h2()也是一种方法,drag()也是如此。

现在问题是 - h2()是在模块中定义的 已经包括了。另一方面,drag()驻留在 对象,还需要一些额外的信息。

我可以在运行时提供此功能,但不能在通话时提供。

换句话说,我需要能够“拦截” drag(),更改它,然后调用该方法 在另一个对象上。

有没有办法逐行评估yield() 还是其他一些方式?我没有必要叫收益率 然而,也有可能得到这个 代码为字符串,修改drag(),然后 eval()就可以了(虽然这听起来很难看,但我 无论如何只需要这个 无论如何)。

2 个答案:

答案 0 :(得分:0)

如果我理解正确,您似乎正在寻找.tap方法。 Tap允许您访问方法链中的中间结果。当然,这需要你重新设置它的设置方式。

答案 1 :(得分:0)

您可以使用instance_eval和代理对象来执行此操作。

一般的想法是这样的:

class DSLProxyObject
  def initialize(proxied_object)
    @target = proxied_object
  end

  def drag
    # Do some stuff
    @target.drag
  end

  def method_missing(method, *args, &block)
    @target.send(method, *args, &block)
  end
end

DSLProxyObject.new(target_object).instance_eval(&block)

您可以实现每个DSL的方法,在调用方法时执行您需要的任何修改,然后在底层对象上调用您需要的内容以使DSL解析。

如果没有一般性的例子,很难完全回答你的问题,但一般的想法是你要创建一个对象上下文,它包含你需要的信息,包装底层的DSL,然后评估那个上下文中的DSL块,这将允许您在每次使用的基础上拦截和修改单个呼叫。