对于 Ruby 2.0+,您可以使用 Kernel#caller_locations 获取程序的当前堆栈跟踪。
来自the docs for Kernel#caller_locations:
caller_locations(start=1, length=nil) → 数组或 nil
source caller_locations(range) → array or nil
返回当前执行堆栈——一个包含回溯的数组
位置对象。
请参阅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 (Kernel#caller_locations 不可用,您必须改用 Kernel#caller:
caller(start=1, length=nil) → array or nil
调用者(范围)→数组或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?