如何为当前请求停止Rails调试器?

时间:2022-12-24 21:16:28

Say I have a loop in my code that calls the rails debugger a few times

比方说,我的代码中有一个循环,它调用rails调试器几次。

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

Assuming I started my server with the --debugger option, when this page is viewed, the debugger is going to stop for every run of the loop.

假设我使用—调试器选项启动了我的服务器,当查看此页面时,调试器将停止运行循环的每一个运行。

I can type cont every time it stops so the request continues, but that's tedious, especially if we're not talking about it showing up 4 times as in this example, but 400. Is there a way to let the debugger continue without pausing at each point of the loop?

每次它停止的时候,我都可以输入cont,这样请求就会继续,但这很繁琐,尤其是如果我们不是说它会出现4次,而是400次。是否有一种方法可以让调试器在循环的每个点上不停顿地继续运行?

My currently workaround is restarting the server, but that's time consuming.

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

8 个解决方案

#1


16  

Just put conditions on the debugger statement so that it stops only when you want it to, e.g.:

只需在调试器语句中添加条件,以便它只在您需要时停止,例如:

debugger if animal == 'tiger'

or if, say, you want to examine the code only on loop 384:

或者,如果,比方说,您只想检查循环384上的代码:

animals.each_with_index do |animal, i|
  debugger if i == 384
  # do something
end

or put in a variable that will let you continue ad hoc:

或者输入一个变量,让你继续特设:

continue_debugger = false
animals.each do |animal|
  debugger unless continue_debugger
  # in the debugger type `p continue_debugger = true` then `c` when done
end

#2


12  

put your debugger statement somewhere before the iteration, then set a breakpoint inside the iteration which you can then clear later.

将调试器语句放在迭代之前的某个地方,然后在迭代中设置一个断点,稍后可以清除该断点。

Example:

例子:

def index

  debugger

  @things = Thing.all
  @things.each do |thing|
    # ... something you want to check out in the debugger
    thing.some_calculation
  end
end

When you enter the debugger, set a breakpoint inside:

当您输入调试器时,在其中设置一个断点:

b app/controllers/things_controller.rb:42

(Where 42 is the line number you want to break at, like thing.some_calculation above. Note that it has to be an executable line of code -- comments, blank lines won't work). The debugger will show a breakpoint number and location:

42是你想要打破的线号。some_calculation以上。请注意,它必须是可执行的代码行——注释、空行不行)。调试器将显示断点号和位置:

Breakpoint 1 at .../app/controllers/things_controller.rb:42

Now, every time you continue, you will stop at the breakpoint. When you're done and want to complete the request, delete the breakpoint:

现在,每次继续,都将在断点处停止。当您完成并想要完成请求时,删除断点:

delete 1

continue once more, and you will complete the request!

再继续,您将完成请求!

#3


5  

It looks like in the source of ruby-debug, the call to debugger will always stop execution whenever it is hit. So one solution is to do as was suggested by Mori in his 'ad-hoc' solution, to make a conditional around the call to debugger that you can tweak inside the debugger session itself, such that you avoid calling debugger. This is probably the neatest solution, and what I would do unless you have some strong nagging purity issues with the code involved.

在ruby-debug的源代码中,对调试器的调用在每次被击中时都将停止执行。一种解决方案是按照Mori在他的“特别”解决方案中建议的那样做,围绕对调试器的调用设置一个条件,您可以在调试器会话本身中进行调整,从而避免调用调试器。这可能是最整洁的解决方案,除非您对所涉及的代码有一些强烈的恼人的纯度问题,否则我将这样做。

If you really want to only do this without some external conditional and inside the debugger session itself, it is possible. What you have to do is set a breakpoint in the code itself, then you can delete that breakpoint in the debugger when it is triggered:

如果您真的想要在没有外部条件和调试器会话本身内部的情况下进行此操作,这是可能的。您需要做的是在代码本身中设置一个断点,然后您可以在触发时删除调试器中的断点:

require 'rubygems'
require 'ruby-debug'

Debugger.start
Debugger.add_breakpoint(__FILE__, __LINE__ + 2)
while true do
  puts "Hi"
  puts "mom"
end
Debugger.stop

This produces this sort of interaction:

这就产生了这种互动:

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

...and so on.

…等等。

In this way, you are setting the breakpoint in code, then deleting it when you are done. Note that any time the line Debugger.add_breakpoint is called, it will re-set the breakpoint, so that's why it is outside of the loop and pointing 2 lines down. This technique can easily be extracted to require-ing a script that sets the breakpoint only when loading your server - Heck, you could write a whole framework class around controlling the Debugger module however you want. Of course, if you went this far, I would just create a singleton class that helps you implement Mori's ad-hoc solution and does or does-not call the debugger statement.

通过这种方式,您正在代码中设置断点,然后在完成时删除它。注意任何时候行调试器。add_breakpoint被调用,它将重新设置断点,这就是为什么它在循环之外并指向下面两行。可以很容易地提取这种技术,以要求在加载服务器时设置断点的脚本——见鬼,您可以围绕控制调试器模块编写一个完整的框架类。当然,如果您走到这一步,我将创建一个单例类,它可以帮助您实现Mori的ad-hoc解决方案,以及是否调用调试器语句。

#4


1  

I came up with another answer to this today that I like even better:

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

debugger unless @no_debug

调试器,除非@no_debug

Use that on every line that has a debugger stop. When you want to stop stopping just set @no_debug to something.

在每一行有调试器停止的代码中使用它。当您想要停止时,只需设置@no_debug。

#5


0  

I have another answer to this one: set a @debug on the class that you want to debug. That way you can do:

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

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

or

  debugger unless !@debug 

then when you are done with the debugger just @debug = false and c.

然后,当您使用调试器时,只需使用@debug = false和c。

However, I'm not really happy with having debugger 'hard stops' in live code. These are the kind of things that can be accidentally checked in and forgotten about until something breaks. The @debug would certainly fall under that as well. To that end I think my ideal solution would use Matt's idea and a script that sets up a breakpoint inside the object when the object is created. That way you'd have the debugging that you want but you wouldn't have any code in source control that is specifically for development. I'll update this answer if I find such a solution.

但是,我不喜欢在实时代码中使用调试器“硬停止”。这些东西可以被意外地检入并遗忘,直到有东西坏掉。@debug肯定也属于这种情况。为此,我认为我的理想解决方案应该使用Matt的思想和在创建对象时在对象内部设置断点的脚本。这样你就有了你想要的调试,但是你在源代码控制中没有专门用于开发的代码。如果我找到这样的解决方案,我会更新这个答案。

#6


0  

You can always comment out the debugger call from your code then type reload in your debug session. Then just cont once and the request will continue without triggering a debug session.

您总是可以注释掉代码中的调试器调用,然后在调试会话中键入reload。然后只等待一次,请求将继续,而不会触发调试会话。

Because you're in development mode, you can just add the debugger call back in later and it will trigger correctly.

因为您处于开发模式,您可以稍后添加调试器调用,它将正确触发。

#7


0  

Putting this here as an alternative since this question showed up first in my own searches. Let's say you have a piece of code that isn't working under a specific circumstance, but works otherwise, and you have a whole slew of tests that exercise this but one specific test that fails. It's a PITA to have to continually type continue into the debug console until you get to the test you really want to debug, so I started using this convention:

把这个放在这里作为替代,因为这个问题首先出现在我自己的搜索中。假设您有一段代码,它在特定的环境下不能工作,但在其他情况下可以工作,您有大量的测试可以使用它,但是有一个特定的测试失败了。需要不断地在调试控制台输入continue,直到您真正想要调试的测试,这是一个PITA,所以我开始使用这个约定:

In your code:

在你的代码:

def some_common_function
  debugger if defined? ::ASDF
  # do something
end

Then in your test:

然后在您的测试:

should "do this thing that it isn't doing under a specific circumstance" do
  # setup the specific situation
  ::ASDF = true
  # your tests
end

#8


0  

If I want control back, I just do

如果我想控制自己,我就这么做

eval return

and I will exit the currently running function, which will usually kick me back to the IRB [rails console] prompt.

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

#1


16  

Just put conditions on the debugger statement so that it stops only when you want it to, e.g.:

只需在调试器语句中添加条件,以便它只在您需要时停止,例如:

debugger if animal == 'tiger'

or if, say, you want to examine the code only on loop 384:

或者,如果,比方说,您只想检查循环384上的代码:

animals.each_with_index do |animal, i|
  debugger if i == 384
  # do something
end

or put in a variable that will let you continue ad hoc:

或者输入一个变量,让你继续特设:

continue_debugger = false
animals.each do |animal|
  debugger unless continue_debugger
  # in the debugger type `p continue_debugger = true` then `c` when done
end

#2


12  

put your debugger statement somewhere before the iteration, then set a breakpoint inside the iteration which you can then clear later.

将调试器语句放在迭代之前的某个地方,然后在迭代中设置一个断点,稍后可以清除该断点。

Example:

例子:

def index

  debugger

  @things = Thing.all
  @things.each do |thing|
    # ... something you want to check out in the debugger
    thing.some_calculation
  end
end

When you enter the debugger, set a breakpoint inside:

当您输入调试器时,在其中设置一个断点:

b app/controllers/things_controller.rb:42

(Where 42 is the line number you want to break at, like thing.some_calculation above. Note that it has to be an executable line of code -- comments, blank lines won't work). The debugger will show a breakpoint number and location:

42是你想要打破的线号。some_calculation以上。请注意,它必须是可执行的代码行——注释、空行不行)。调试器将显示断点号和位置:

Breakpoint 1 at .../app/controllers/things_controller.rb:42

Now, every time you continue, you will stop at the breakpoint. When you're done and want to complete the request, delete the breakpoint:

现在,每次继续,都将在断点处停止。当您完成并想要完成请求时,删除断点:

delete 1

continue once more, and you will complete the request!

再继续,您将完成请求!

#3


5  

It looks like in the source of ruby-debug, the call to debugger will always stop execution whenever it is hit. So one solution is to do as was suggested by Mori in his 'ad-hoc' solution, to make a conditional around the call to debugger that you can tweak inside the debugger session itself, such that you avoid calling debugger. This is probably the neatest solution, and what I would do unless you have some strong nagging purity issues with the code involved.

在ruby-debug的源代码中,对调试器的调用在每次被击中时都将停止执行。一种解决方案是按照Mori在他的“特别”解决方案中建议的那样做,围绕对调试器的调用设置一个条件,您可以在调试器会话本身中进行调整,从而避免调用调试器。这可能是最整洁的解决方案,除非您对所涉及的代码有一些强烈的恼人的纯度问题,否则我将这样做。

If you really want to only do this without some external conditional and inside the debugger session itself, it is possible. What you have to do is set a breakpoint in the code itself, then you can delete that breakpoint in the debugger when it is triggered:

如果您真的想要在没有外部条件和调试器会话本身内部的情况下进行此操作,这是可能的。您需要做的是在代码本身中设置一个断点,然后您可以在触发时删除调试器中的断点:

require 'rubygems'
require 'ruby-debug'

Debugger.start
Debugger.add_breakpoint(__FILE__, __LINE__ + 2)
while true do
  puts "Hi"
  puts "mom"
end
Debugger.stop

This produces this sort of interaction:

这就产生了这种互动:

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

...and so on.

…等等。

In this way, you are setting the breakpoint in code, then deleting it when you are done. Note that any time the line Debugger.add_breakpoint is called, it will re-set the breakpoint, so that's why it is outside of the loop and pointing 2 lines down. This technique can easily be extracted to require-ing a script that sets the breakpoint only when loading your server - Heck, you could write a whole framework class around controlling the Debugger module however you want. Of course, if you went this far, I would just create a singleton class that helps you implement Mori's ad-hoc solution and does or does-not call the debugger statement.

通过这种方式,您正在代码中设置断点,然后在完成时删除它。注意任何时候行调试器。add_breakpoint被调用,它将重新设置断点,这就是为什么它在循环之外并指向下面两行。可以很容易地提取这种技术,以要求在加载服务器时设置断点的脚本——见鬼,您可以围绕控制调试器模块编写一个完整的框架类。当然,如果您走到这一步,我将创建一个单例类,它可以帮助您实现Mori的ad-hoc解决方案,以及是否调用调试器语句。

#4


1  

I came up with another answer to this today that I like even better:

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

debugger unless @no_debug

调试器,除非@no_debug

Use that on every line that has a debugger stop. When you want to stop stopping just set @no_debug to something.

在每一行有调试器停止的代码中使用它。当您想要停止时,只需设置@no_debug。

#5


0  

I have another answer to this one: set a @debug on the class that you want to debug. That way you can do:

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

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

or

  debugger unless !@debug 

then when you are done with the debugger just @debug = false and c.

然后,当您使用调试器时,只需使用@debug = false和c。

However, I'm not really happy with having debugger 'hard stops' in live code. These are the kind of things that can be accidentally checked in and forgotten about until something breaks. The @debug would certainly fall under that as well. To that end I think my ideal solution would use Matt's idea and a script that sets up a breakpoint inside the object when the object is created. That way you'd have the debugging that you want but you wouldn't have any code in source control that is specifically for development. I'll update this answer if I find such a solution.

但是,我不喜欢在实时代码中使用调试器“硬停止”。这些东西可以被意外地检入并遗忘,直到有东西坏掉。@debug肯定也属于这种情况。为此,我认为我的理想解决方案应该使用Matt的思想和在创建对象时在对象内部设置断点的脚本。这样你就有了你想要的调试,但是你在源代码控制中没有专门用于开发的代码。如果我找到这样的解决方案,我会更新这个答案。

#6


0  

You can always comment out the debugger call from your code then type reload in your debug session. Then just cont once and the request will continue without triggering a debug session.

您总是可以注释掉代码中的调试器调用,然后在调试会话中键入reload。然后只等待一次,请求将继续,而不会触发调试会话。

Because you're in development mode, you can just add the debugger call back in later and it will trigger correctly.

因为您处于开发模式,您可以稍后添加调试器调用,它将正确触发。

#7


0  

Putting this here as an alternative since this question showed up first in my own searches. Let's say you have a piece of code that isn't working under a specific circumstance, but works otherwise, and you have a whole slew of tests that exercise this but one specific test that fails. It's a PITA to have to continually type continue into the debug console until you get to the test you really want to debug, so I started using this convention:

把这个放在这里作为替代,因为这个问题首先出现在我自己的搜索中。假设您有一段代码,它在特定的环境下不能工作,但在其他情况下可以工作,您有大量的测试可以使用它,但是有一个特定的测试失败了。需要不断地在调试控制台输入continue,直到您真正想要调试的测试,这是一个PITA,所以我开始使用这个约定:

In your code:

在你的代码:

def some_common_function
  debugger if defined? ::ASDF
  # do something
end

Then in your test:

然后在您的测试:

should "do this thing that it isn't doing under a specific circumstance" do
  # setup the specific situation
  ::ASDF = true
  # your tests
end

#8


0  

If I want control back, I just do

如果我想控制自己,我就这么做

eval return

and I will exit the currently running function, which will usually kick me back to the IRB [rails console] prompt.

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