如何为当前请求停止Rails调试器
假设我的代码中有一个循环调用rails调试器几次
def show animals = ['dog', 'cat', 'owl', 'tiger'] for animal in animals debugger # do something else end
假设我使用--debugger
选项启动了我的服务器,当查看此页面时,调试器将在每次循环运行时停止。
我可以在每次停止时键入cont
,因此请求仍在继续,但这很乏味,特别是如果我们不是在谈论它在本例中显示4次,而是400.有没有办法让调试器继续而不停顿循环的每个点?
我目前的解决方法是重新启动服务器,但这很耗时。
只需在调试器语句上添加条件,使其仅在您需要时停止,例如:
debugger if animal == 'tiger'
或者,如果您想要仅在循环384上检查代码:
animals.each_with_index do |animal, i| debugger if i == 384 # do something end
或者放入一个可以让你继续临时的变量:
continue_debugger = false animals.each do |animal| debugger unless continue_debugger # in the debugger type `p continue_debugger = true` then `c` when done end
在迭代之前将debugger
语句放在某处,然后在迭代中设置一个断点,稍后可以清除该断点。
例:
def index debugger @things = Thing.all @things.each do |thing| # ... something you want to check out in the debugger thing.some_calculation end end
进入调试器时,在内部设置断点:
b app/controllers/things_controller.rb:42
(其中42是你要打破的行号,比如上面的thing.some_calculation
。注意它必须是一段可执行的代码 – 注释,空白行不起作用)。 调试器将显示断点编号和位置:
Breakpoint 1 at .../app/controllers/things_controller.rb:42
现在,每次你继续,你都会在断点处停下来。 当您完成并想要完成请求时,删除断点:
delete 1
再次继续,您将完成请求!
看起来在ruby-debug的源代码中,对debugger
的调用将始终在命中时停止执行。 因此,一个解决方案是按照Mori在他的’ad-hoc’解决方案中所建议的那样做,以调用调试器的调用为条件,你可以在调试器会话本身内调整,这样就可以避免调用debugger
。 这可能是最好的解决方案,除非你对所涉及的代码有一些强烈的唠叨纯度问题,否则我会做什么。
如果你真的只想在没有一些外部条件的情况下在调试器会话本身内执行此操作,那么它是可能的。 您需要做的是在代码本身中设置一个断点,然后您可以在调试器中触发它时删除该断点:
require 'rubygems' require 'ruby-debug' Debugger.start Debugger.add_breakpoint(__FILE__, __LINE__ + 2) while true do puts "Hi" puts "mom" end Debugger.stop
这产生了这种互动:
Breakpoint 1 at debug_test.rb:10 debug_test.rb:10 puts "Hi" (rdb:1) c Hi mom Breakpoint 1 at debug_test.rb:10 debug_test.rb:10 puts "Hi" (rdb:1) c Hi mom Breakpoint 1 at debug_test.rb:10 debug_test.rb:10 puts "Hi" (rdb:1) info b Num Enb What 1 y at ./debug_test.rb:10 breakpoint already hit 3 times (rdb:1) del 1 (rdb:1) c Hi mom Hi mom Hi mom
…等等。
这样,您将在代码中设置断点,然后在完成后将其删除。 请注意,无论何时调用Debugger.add_breakpoint
行,它都会重新设置断点,这就是它在循环之外并指向2行的原因。 这个技术很容易被提取出来,只require
一个只在加载你的服务器时设置断点的脚本 – 哎呀,你可以根据需要编写一个完整的框架类来控制Debugger模块。 当然,如果你走得这么远,我只会创建一个单例类来帮助你实现Mori的临时解决方案,并且不会或者不会调用调试器语句。
我今天想出了另一个答案,我更喜欢这个:
debugger unless @no_debug
在具有调试器停止的每一行上使用它。 当你想停止停止时只需设置@no_debug即可。
我有另一个答案:在你要调试的类上设置一个@debug
。 这样你就可以做到:
if (@debug && (the_condition)) then debugger end
要么
debugger unless !@debug
然后当你完成调试器只需@debug = false
和c
。
但是,在实时代码中调试器“硬停止”我真的不高兴。 这些东西可能会被意外检查并被遗忘,直到出现故障。 @debug
肯定也属于这个。 为此,我认为我的理想解决方案将使用Matt的想法和一个脚本,该脚本在创建对象时在对象内部设置断点。 这样你就可以得到你想要的调试,但你不会在源代码管理中有任何专门用于开发的代码。 如果我找到这样的解决方案,我会更新这个答案。
您始终可以从代码中注释掉debugger
调用,然后在调试会话中键入reload
。 然后只需一次,请求将继续,而不会触发调试会话。
因为您处于开发模式,所以您可以稍后添加debugger
回调,它将正确触发。
把这个放在这里作为替代,因为这个问题首先出现在我自己的搜索中。 假设您有一段代码在特定情况下无法正常工作,但在其他情况下工作,并且您有一大堆测试可以执行此操作,但是一个特定测试失败了。 这是一个PITA必须不断输入continue
进入调试控制台,直到你真正想要调试的测试,所以我开始使用这个约定:
在你的代码中:
def some_common_function debugger if defined? ::ASDF # do something end
然后在你的测试中:
should "do this thing that it isn't doing under a specific circumstance" do # setup the specific situation ::ASDF = true # your tests end
如果我想要控制权,我就这样做
eval return
然后我将退出当前运行的函数,这通常会让我回到IRB [rails console]提示符。