Как остановить отладчик 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
выйдите из отладчика из цикла, используйте
экзит-все
вместо
продолжение