15

假设我的代码中有一个循环调用 rails 调试器几次

def show
    animals = ['dog', 'cat', 'owl', 'tiger']
    for animal in animals
    debugger
    # do something else
end

假设我使用该选项启动我的服务器--debugger,当查看此页面时,调试器将在每次运行循环时停止。

我可以在cont每次它停止时输入,以便请求继续,但这很乏味,特别是如果我们不是在这个例子中谈论它显示 4 次,而是 400 次。有没有办法让调试器继续而不在每个暂停循环点?

我目前的解决方法是重新启动服务器,但这很耗时。

4

9 回答 9

16

只需在调试器语句上设置条件,以便它仅在您需要时停止,例如:

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
于 2011-05-31T12:09:33.277 回答
12

将您的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

再次继续,您将完成请求!

于 2011-06-16T20:20:10.533 回答
5

它看起来像在 ruby​​-debug 的源代码中,调用总是debugger会在它被命中时停止执行。因此,一种解决方案是按照 Mori 在他的“临时”解决方案中所建议的那样做,围绕对调试器的调用设置一个条件,您可以在调试器会话本身内部进行调整,这样您就可以避免调用. 这可能是最简洁的解决方案,除非您对所涉及的代码有一些强烈的令人讨厌的纯度问题,否则我会这样做。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仅在加载服务器时设置断点的脚本 - 哎呀,你可以编写一个完整的框架类来控制调试器模块,但是你想要。当然,如果您走到这一步,我只会创建一个单例类来帮助您实现 Mori 的临时解决方案并调用或不调用调试器语句。

于 2011-06-17T02:17:02.960 回答
1

我今天想出了另一个我更喜欢的答案:

debugger unless @no_debug

在具有调试器停止的每一行上使用它。当您想停止停止时,只需将 @no_debug 设置为某个值。

于 2012-04-29T23:21:26.467 回答
0

我对此有另一个答案:@debug在要调试的类上设置 a 。这样你就可以做到:

  if (@debug && (the_condition)) then debugger end

或者

  debugger unless !@debug 

然后当你完成调试器时,只需@debug = falsec.

但是,我对在实时代码中使用调试器“硬停止”并不满意。这些东西可能会被意外签入并被遗忘,直到出现问题。@debug当然也属于这个范围。为此,我认为我理想的解决方案将使用Matt 的想法和一个在创建对象时在对象内部设置断点的脚本。这样,您就可以进行所需的调试,但在源代码控制中不会有任何专门用于开发的代码。如果我找到这样的解决方案,我会更新这个答案。

于 2012-01-21T16:43:02.790 回答
0

您可以随时从代码中注释掉debugger调用,然后输入reload调试会话。然后只需cont一次,请求将继续,而不会触发调试会话。

因为您处于开发模式,您可以debugger稍后再添加调用,它会正确触发。

于 2012-08-10T21:55:17.660 回答
0

把它放在这里作为替代,因为这个问题首先出现在我自己的搜索中。假设您有一段代码在特定情况下无法正常工作,但在其他情况下可以正常工作,并且您有大量测试可以执行此操作,但有一个特定测试失败。continue在你真正想要调试的测试之前,必须不断地在调试控制台中输入,这是一个 PITA ,所以我开始使用这个约定:

在您的代码中:

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
于 2014-05-27T18:56:11.610 回答
0

如果我想要控制权,我就这么做

eval return

我将退出当前正在运行的函数,这通常会将我踢回 IRB [rails 控制台] 提示符。

于 2016-10-28T10:59:10.770 回答
0

退出循环调试器,使用

全部退出

代替

虽然,它会产生一个错误,您可能必须删除调试器并再次发送请求,但它会让您摆脱所有循环

于 2019-07-25T05:47:17.317 回答