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

我知道有可能在ruby中使用挂钩之前和之后修饰方法,但是可以为给定方法的每一行执行此操作吗?

例如,我有一个自动化测试,我想validation每个步骤后页面上没有显示错误。 错误显示为红色div,并且对于Ruby不可见或者类似的东西,因此我必须手动检查它(还有其他几个用例)。

我知道可能使用set_trace_func 。 但我认为这可能会带来更多问题而不是好处,因为它可以在整个调用树上运行(并且需要我自己过滤它)。

更新(澄清)

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

它是,您可以在Ruby编程语言的第8.9节中获得有关如何执行此操作的完整说明。 在每次调用方法时运行代码涉及将方法发送到具有method_missing实现的TracedObject类。 无论何时收到消息,它都会调用method_missing并执行您为其分配的任何代码。 (当然,这是一般追踪)。

这是对此过程的一般描述,您可以查阅本书了解详细信息。

听起来您希望跟踪每个对象上的每个方法调用,但仅限于对每个特定方法的每次调用的跨度。 在这种情况下,您可以重新定义方法以打开和关闭仪器。 首先,使用Pinochle答案中提出的通用仪器,然后重新定义所讨论的方法如下:

 # 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 

你需要编写install!uninstall方法,但它们应该是非常简单的:只需设置或取消设置类变量并在检测逻辑中检查它。

怎么样(只是尝试)

  class User def initialize(name) @name = name end def say_hello puts "hello #{@name}" end def say_hi(friend) puts "hi #{@name} from #{friend}" end def say_bye(a, b = 'Anna') puts "bye #{a} and #{b}" end end User.class_eval do User.instance_methods(false).each do |method| original = instance_method(method) define_method method do |*options| parameters = original.parameters if parameters.empty? original.bind(self).call else original.bind(self).call(*options) end puts __method__ end end end user = User.new("John") user.say_hello user.say_hi("Bob") user.say_bye("Bob") user.say_bye("Bob", "Lisa") 

输出:

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