如the Pry wiki article on hooks 中所述,使用 Pry before_session 钩子。
before_session 钩子在调用 binding.pry 时将您放入 REPL 之前执行。每次您调用 binding.pry 来调用 whereami --quiet 时,Pry 都会使用 before_session 挂钩,就像您在帖子中所说的那样:
From: /opt/hobbyonrails/spec/support/alias.rb:12 :
7:
8: rspec.before(:example, pry: true) do |_|
9: # rubocop:disable Lint/Debugger
10: binding.pry
11: # rubocop:enable Lint/Debugger
=> 12: end
13: end
使用before_session 钩子解决问题的想法是告诉Pry,当它被调用时,它应该自动调用step 25。 (或者你需要多少步骤)
这有点棘手,因为来自 pry-byebug 的 step 命令实际上调用了一个新的 Pry 会话。如果您添加一个调用step 的before_session 钩子,然后step 调用一个新会话,您将陷入一个循环,直到程序完成执行为止。
另一个问题是,在添加钩子后执行的代码中对binding.pry 的任何调用都会再次调用step,您可能不希望它每次都调用step,只是在一个特定的点。
解决这个问题的方法是添加一个在执行时自行移除的钩子:
Pry.hooks.add_hook(:before_session, 'step') do |output, binding, pry|
Pry.hooks.delete_hook(:before_session, 'step')
pry.run_command('step 1')
end
现在流程应该是:
- 上面的钩子加了
-
binding.pry 被调用
- 上面的钩子被执行,移除钩子并运行
step 1
-
step 调用新的 Pry 会话
- 上面的钩子不再存在,也没有执行
- REPL 打开
- 任何进一步的
binding.pry 调用都不会执行挂钩
这里有一个示例应用程序来展示它是如何工作的:
require 'pry'
require 'pry-byebug'
Pry.hooks.add_hook(:before_session, 'step') do |output, binding, pry|
Pry.hooks.delete_hook(:before_session, 'step')
pry.run_command('step 1')
end
binding.pry
puts 'Pry will run `whereami` and point at this line with => first'
puts 'But when the hook runs it will step to and point at this line with =>'
puts 'And it will stop before it reaches this line'
binding.pry
puts 'And after this second binding, there will be no hook and thus no step'
puts 'And it will stop before it reaches this line'
这是它的输出,证明它按描述工作:
$ ruby foo.rb
From: /Users/foo/foo.rb:10 :
5: Pry.hooks.delete_hook(:before_session, 'step')
6: pry.run_command('step 1')
7: end
8:
9: binding.pry
=> 10: puts 'Pry will run `whereami` and point at this line with => first'
11: puts 'But when the hook runs it will step to and point at this line with =>'
12: puts 'And it will stop before it reaches this line'
13:
14: binding.pry
15: puts 'And after this second binding, there will be no hook and thus no step'
Pry will run `whereami` and point at this line with => first
From: /Users/foo/foo.rb:11 :
6: pry.run_command('step 1')
7: end
8:
9: binding.pry
10: puts 'Pry will run `whereami` and point at this line with => first'
=> 11: puts 'But when the hook runs it will step to and point at this line with =>'
12: puts 'And it will stop before it reaches this line'
13:
14: binding.pry
15: puts 'And after this second binding, there will be no hook and thus no step'
16: puts 'And it will stop before it reaches this line'
foo|(main):1 ⇒ exit
But when the hook runs it will step to and point at this line with =>
And it will stop before it reaches this line
From: /Users/foo/foo.rb:15 :
10: puts 'Pry will run `whereami` and point at this line with => first'
11: puts 'But when the hook runs it will step to and point at this line with =>'
12: puts 'And it will stop before it reaches this line'
13:
14: binding.pry
=> 15: puts 'And after this second binding, there will be no hook and thus no step'
16: puts 'And it will stop before it reaches this line'
foo|(main):1 ⇒
将其集成到您的应用中应该非常简单:
rspec.before(:example, pry: true) do |_|
# rubocop:disable Lint/Debugger
# You should find a good way to set this value as it seems likely to change
steps = 25
Pry.hooks.add_hook(:before_session, 'step') do |output, binding, pry|
Pry.hooks.delete_hook(:before_session, 'step')
pry.run_command("step #{steps}")
end
binding.pry
# rubocop:enable Lint/Debugger
end