我想在一个函数中启动一个Pry会话,但由于我正在研究的项目中有一些元编程,Pry会在很多我不感兴趣的环境中被触发。如何根据程序当前执行的堆栈跟踪触发pry?
类似的东西,
binding.pry if stacktrace.include? "function_name"
答案 0 :(得分:2)
对于Ruby 2.0+,您可以使用Kernel#caller_locations
来获取程序的当前堆栈跟踪。
来自the docs for Kernel#caller_locations
:
caller_locations(start = 1,length = nil)→array或nil
source caller_locations(range)→array或nil
返回当前执行堆栈 - 包含backtrace的数组 位置对象。
有关详细信息,请参阅
Thread::Backtrace::Location
。
正如我们从文档中看到的,此方法返回一个Thread::Backtrace::Location
个对象数组,您可以使用它们来确定是否调用binding.pry
。 Thread::Backtrace::Location
提供了一个名为base_label
的方法,该方法返回堆栈中当前位置的方法名称。您可以使用它来检查当前堆栈跟踪是否通过具有特定名称的方法运行。
用法示例:
def a
caller_locations(0)
end
def b
a
end
def c
b
end
c.map(&:base_label)
#=> ["a", "b", "c", "<main>"]
所以在你的情况下,你会像这样使用它:
binding.pry if caller_locations.map(&:base_label).include? function_name
如果您使用的是旧版本的Ruby(&lt; 2.0),则Kernel#caller_locations
不可用,您必须使用Kernel#caller
代替:
调用者(start = 1,length = nil)→array或nil
来电者(范围)→数组或无
返回当前执行堆栈 - 包含字符串的数组 表单文件:行或文件:行:在`方法'。
可选的start参数确定初始堆栈的数量 要从堆栈顶部省略的条目。
第二个可选长度参数可用于限制数量 条目从堆栈返回。
如果start大于当前执行的大小,则返回nil 叠加。
您可以选择传递一个范围,该范围将返回包含的数组 指定范围内的条目。
def a(skip) caller(skip) end def b(skip) a(skip) end def c(skip) b(skip) end c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"] c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"] c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"] c(3) #=> ["prog:13:in `<main>'"] c(4) #=> [] c(5) #=> nil
您会注意到Kernel#caller_locations
和Kernel#caller
之间的唯一区别是Kernel#caller
返回一个字符串数组,而不是Thread::Backtrace::Location
个对象的数组。这意味着您必须使用正则表达式之类的方法来匹配方法名称,而不是像使用Kernel#caller_locations
那样只使用Array#include?
。在你的情况下:
binding.pry if caller.any?{|stack_entry| stack_entry =~ /in `#{function_name}'$/}
有关在Ruby中获取堆栈跟踪的更多信息,请参阅how to get a stack trace object in Ruby?
答案 1 :(得分:1)
尝试
binding.pry if caller.any?{|fn_name| fn_name.include?('function_name')}