Как остановить отладчик Rails для текущего запроса

Скажем, у меня есть цикл в моем коде, который несколько раз вызывает отладчик rails

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

Предполагая, что я начал свой сервер с опцией --debugger, когда эта страница просматривается, отладчик остановится для каждого запуска цикла.

Я могу набирать cont каждый раз, когда он останавливается, поэтому запрос продолжается, но это утомительно, особенно если мы не говорим об этом, он появляется в 4 раза, как в этом примере, но 400. Есть ли способ отпустить отладчик без паузы в каждой точке цикла?

Моим обходным путем является перезапуск сервера, но это занимает много времени.

Ответы

Ответ 1

Просто установите условия в инструкции отладчика, чтобы он останавливался только тогда, когда вы хотите, например:

debugger if animal == 'tiger'

или, если, скажем, вы хотите изучить код только в цикле 384:

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

или введите переменную, которая позволит вам продолжить 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

поставьте свой оператор 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

продолжить еще раз, и вы заполните запрос!

Ответ 3

Похоже, что в источнике ruby-debug вызов debugger всегда прекращает выполнение всякий раз, когда он попадает. Таким образом, одно решение - это сделать так, как было предложено Мори в его "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 -ing script, который устанавливает точку останова только при загрузке вашего сервера. Heck, вы могли бы написать целый класс framework, контролируя модуль Debugger, но вы хотите. Конечно, если бы вы зашли так далеко, я бы просто создал одноэлементный класс, который поможет вам внедрить специальное решение Mori и делает или не вызывает оператор отладчика.

Ответ 4

Я придумал еще один ответ на этот вопрос сегодня, который мне нравится еще лучше:

debugger unless @no_debug

Используйте это в каждой строке, где есть отладчик. Если вы хотите остановить остановку, просто установите @no_debug на что-то.

Ответ 5

У меня есть еще один ответ на этот вопрос: установите @debug в классе, который вы хотите отлаживать. Таким образом вы можете:

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

или

  debugger unless [email protected] 

тогда, когда вы закончите с отладчиком только @debug = false и c.

Тем не менее, я не очень доволен тем, что у меня есть отладчик "жесткие остановки" в реальном коде. Это те вещи, которые можно случайно проверить и забыть, пока что-то не сломается. @debug, безусловно, подпадает под это. С этой целью я думаю, что мое идеальное решение будет использовать идею Мэтта и script, которая устанавливает точку останова внутри объекта при создании объекта. Таким образом, у вас будет отладка, которую вы хотите, но у вас не будет никакого кода в исходном контроле, который специально предназначен для разработки. Я обновлю этот ответ, если найду такое решение.

Ответ 6

Вы всегда можете прокомментировать вызов debugger из своего кода, а затем введите reload в свой отладочный сеанс. Затем просто cont один раз, и запрос будет продолжен без запуска сеанса отладки.

Поскольку вы находитесь в режиме разработки, вы можете просто добавить обратный вызов debugger позже, и он будет запускаться правильно.

Ответ 7

Поместите это здесь как альтернативу, так как этот вопрос появился в моих собственных поисках. Скажем, у вас есть часть кода, которая не работает при определенных обстоятельствах, но работает иначе, и у вас есть целая серия тестов, которые выполняют это, но один конкретный тест, который терпит неудачу. Это 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

Ответ 8

Если я хочу вернуть управление, я просто делаю

eval return

и я выйду из текущей функции, которая, как правило, возвращает меня в приглашение IRB [rails console].

Ответ 9

выйдите из отладчика из цикла, используйте

экзит-все

вместо

продолжение