[英]Is it possible to run code after each line in Ruby?
I understand that it is possible to decorate methods with before and after hooks in ruby, but is it possible to do it for each line of a given method? 我知道可以在ruby中使用挂钩之前和之后修饰方法,但是是否可以为给定方法的每一行执行此操作?
For example, I have an automation test and I want to verify that after each step there no error shown on the page. 例如,我有一个自动化测试,我想验证每个步骤后页面上没有显示错误。 The error is shown as a red div and is not visible to Ruby as
raise
or anything like that, so I have to check for it manually (there are several other use cases as well). 该错误显示为红色的div和不可见的红宝石作为
raise
之类的东西,所以我必须手动检查它(还有其他一些使用情况以及)。
I understand that it might be possible using set_trace_func
. 我知道使用
set_trace_func
可能是可能的。 But I think this may bring more problems than benefits since it works over entire call tree (and requires me to filter it myself). 但我认为这可能会带来更多问题而不是好处,因为它可以在整个调用树上运行(并且需要我自己过滤它)。
UPDATE (clarification) : 更新(澄清) :
I am interested in intercepting all actions (or calls) that are performed within a given method. 我有兴趣拦截在给定方法中执行的所有操作(或调用)。 This means unspecified number of classes is called, so I can't just intercept any given set of classes/methods.
这意味着调用了未指定数量的类,因此我不能只截取任何给定的类/方法集。
It is, and you can get a full description of how to do it in section 8.9 of The Ruby Programming Language . 它是,您可以在Ruby编程语言的第8.9节中获得如何执行此操作的完整描述。 Running the code on each invocation of the method involves sending the method to a
TracedObject
class that has an implementation for method_missing
. 在每次调用方法时运行代码涉及将方法发送到具有
method_missing
实现的TracedObject
类。 Whenever it receives a message, it invokes method_missing
and executes whatever code you have assigned to it. 每当它收到一条消息时,它就会调用
method_missing
并执行你分配给它的任何代码。 (This is, of course, for general tracing). (当然,这是一般追踪)。
That's the general description of the procedure for doing it, you can consult the book for details. 这是对此过程的一般描述,您可以查阅本书了解详细信息。
It sounds like you want tracing on every method call on every object, but only during the span of every call to one particular method. 这听起来像你想跟踪的每个对象的每一个方法调用,但只在每次调用一个 特定方法的跨度。 In that case, you could just redefine the method to turn on- and off instrumentation.
在这种情况下,您可以重新定义方法以打开和关闭仪器。 First, use the universal instrumentation suggsted in Pinochle's answer , then redefine the method in question as follows:
首先,使用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
You'd need to write the install!
你需要编写
install!
and uninstall
methods, but they should be pretty trivial: just set or unset a class variable and check for it in the instrumentation logic. 和
uninstall
方法,但它们应该是非常简单的:只需设置或取消设置类变量并在检测逻辑中检查它。
What about (just tries) 怎么样(只是尝试)
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")
outputs: 输出:
hello John
say_hello
hi John from Bob
say_hi
bye Bob and Anna
say_bye
bye Bob and Lisa
say_bye
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.