根据堆栈跟踪的内容触发 Pry 绑定
Triggering Pry binding based on contents of stacktrace
我想在一个函数中启动一个 Pry 会话,但是由于我现在正在处理的项目中的一些元编程,Pry 在很多我不感兴趣的上下文中被触发。如何我可以根据程序当前执行的堆栈跟踪触发撬吗?
有点像,
binding.pry if stacktrace.include? "function_name"
尝试
binding.pry if caller.any?{|fn_name| fn_name.include?('function_name')}
参考:How to get a stack trace object in Ruby?
对于Ruby 2.0+,您可以使用Kernel#caller_locations
获取程序的当前堆栈跟踪。
来自 the docs for Kernel#caller_locations
:
caller_locations(start=1, length=nil) → array or nil
source caller_locations(range) → array or nil
Returns the current execution stack—an array containing backtrace
location objects.
See Thread::Backtrace::Location
for more information.
所以我们从文档中可以看出,这个方法returns一个Thread::Backtrace::Location
objects, which you can use to determine whether or not to call binding.pry
. Thread::Backtrace::Location
provides a method called base_label
的数组,其中returns方法名在栈中的当前位置。您可以使用它来检查当前堆栈跟踪是否通过具有特定名称的方法运行。
用法示例:
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 (< 2.0),Kernel#caller_locations
不可用,您必须使用 Kernel#caller
改为:
caller(start=1, length=nil) → array or nil
caller(range) → array or nil
Returns the current execution stack—an array containing strings in the
form file:line or file:line: in `method'.
The optional start parameter determines the number of initial stack
entries to omit from the top of the stack.
A second optional length parameter can be used to limit how many
entries are returned from the stack.
Returns nil if start is greater than the size of current execution
stack.
Optionally you can pass a range, which will return an array containing
the entries within the specified range.
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
returns 是一个字符串数组,而不是 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?
我想在一个函数中启动一个 Pry 会话,但是由于我现在正在处理的项目中的一些元编程,Pry 在很多我不感兴趣的上下文中被触发。如何我可以根据程序当前执行的堆栈跟踪触发撬吗?
有点像,
binding.pry if stacktrace.include? "function_name"
尝试
binding.pry if caller.any?{|fn_name| fn_name.include?('function_name')}
参考:How to get a stack trace object in Ruby?
对于Ruby 2.0+,您可以使用Kernel#caller_locations
获取程序的当前堆栈跟踪。
来自 the docs for Kernel#caller_locations
:
caller_locations(start=1, length=nil) → array or nil
source caller_locations(range) → array or nil
Returns the current execution stack—an array containing backtrace location objects.
See
Thread::Backtrace::Location
for more information.
所以我们从文档中可以看出,这个方法returns一个Thread::Backtrace::Location
objects, which you can use to determine whether or not to call binding.pry
. Thread::Backtrace::Location
provides a method called base_label
的数组,其中returns方法名在栈中的当前位置。您可以使用它来检查当前堆栈跟踪是否通过具有特定名称的方法运行。
用法示例:
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 (< 2.0),Kernel#caller_locations
不可用,您必须使用 Kernel#caller
改为:
caller(start=1, length=nil) → array or nil
caller(range) → array or nil
Returns the current execution stack—an array containing strings in the form file:line or file:line: in `method'.
The optional start parameter determines the number of initial stack entries to omit from the top of the stack.
A second optional length parameter can be used to limit how many entries are returned from the stack.
Returns nil if start is greater than the size of current execution stack.
Optionally you can pass a range, which will return an array containing the entries within the specified range.
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
returns 是一个字符串数组,而不是 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?