可以在Ruby中的每一行之后运行代码吗?

可以在Ruby中的每一行之后运行代码吗?,ruby,metaprogramming,Ruby,Metaprogramming,我知道在ruby中可以用before和after钩子装饰方法,但是对于给定方法的每一行,是否可以这样做呢 例如,我有一个自动化测试,我想验证在每个步骤之后页面上没有显示错误。错误显示为红色div,Ruby看不到它是raise或类似的东西,因此我必须手动检查它(还有其他几个用例) 我知道可以使用set\u trace\u func。但我认为这可能带来更多的问题而不是好处,因为它适用于整个调用树(并且需要我自己对其进行过滤) 更新(澄清): 我感兴趣的是拦截在给定方法中执行的所有操作(或调用)。这意

我知道在ruby中可以用before和after钩子装饰方法,但是对于给定方法的每一行,是否可以这样做呢

例如,我有一个自动化测试,我想验证在每个步骤之后页面上没有显示错误。错误显示为红色div,Ruby看不到它是
raise
或类似的东西,因此我必须手动检查它(还有其他几个用例)

我知道可以使用
set\u trace\u func
。但我认为这可能带来更多的问题而不是好处,因为它适用于整个调用树(并且需要我自己对其进行过滤)

更新(澄清)


我感兴趣的是拦截在给定方法中执行的所有操作(或调用)。这意味着调用了数量不确定的类,因此我不能只截取任何给定的类/方法集。

是的,您可以在的第8.9节中获得如何进行截取的完整描述。每次调用该方法时运行代码都需要将该方法发送到
TraceObject
类,该类具有
method\u missing
的实现。每当它收到消息时,它就会调用
方法\u missing
,并执行您分配给它的任何代码。(当然,这是用于一般跟踪)


这是执行此操作过程的一般说明,有关详细信息,您可以查阅本书。

听起来您希望跟踪每个对象上的每个方法调用,但仅限于对一个特定方法的每次调用期间。在这种情况下,您可以重新定义方法来打开和关闭检测。首先,使用中建议的通用仪器,然后重新定义所述方法,如下所示:

# original definition, in /lib/foo.rb:
class Foo
  def bar(baz)
    do_stuff
  end
end

# redefinition, in /test/add_instrumentation_to_foo.rb:
Foo.class_eval do
  original_bar = instance_method(:bar)
  def bar(baz)
    TracedObject.install!
    original_bar.bind(self).call(baz)
    TracedObject.uninstall!
  end
end
您需要编写
安装
卸载
方法,但它们应该非常简单:只需设置或取消设置一个类变量,并在检测逻辑中检查它。

怎么样(只需尝试)

产出:

    hello John
    say_hello
    hi John from Bob
    say_hi
    bye Bob and Anna
    say_bye
    bye Bob and Lisa
    say_bye

我的理解是TraceObject(?)可以截获对给定类的方法的所有调用,但是如果我想截获来自特定方法的所有调用呢?所讨论的方法可能调用多个类,因此它本质上要求我将所有调用的类包装在TraceObject中(这似乎不可能作为一般解决方案)?如果您对单个方法感兴趣,您只需筛选
方法\u missing
的内部;但是你说你不喜欢过滤的想法。您是对的,对于一个在多个类上传递消息的方法来说,这将是一个不雅观到困难的解决方案。也许您应该编辑这个问题来添加第二个要求(关于几个类)。我对单个方法的传出调用感兴趣,而不是对它的传入调用。或者我想截取原始方法的每一行,如原始问题中所述。哈,你会杀了我,但我认为你想要的是在8.11.3中找到的。“Ruby编程语言”,但您仍然需要在使用方法的每个类中设置跟踪。至少,你可以用它作为一个解决方案的起点,它可以让你逐行追踪。这很酷,我现在知道了特征类是什么了。但它仍然需要我调用trace!在方法中使用的每个实例上。经过一些考虑,我想我会使用set_trace_func——我会在完成后发布一个示例作为回复。如果我正确阅读了8.11.3,那么就不应该有一个全局TraceObject.install!可用,因为它不是自我安装!,它仅在实例级别可用。
    hello John
    say_hello
    hi John from Bob
    say_hi
    bye Bob and Anna
    say_bye
    bye Bob and Lisa
    say_bye