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

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

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

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

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

Мой текущий обходной путь — перезапуск сервера, но это занимает много времени.


person Yuval Karmi    schedule 31.05.2011    source источник
comment
Перестать продолжать делать паузу — усложняющее выражение. Я исправил это соответственно.   -  person sawa    schedule 31.05.2011


Ответы (9)


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

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
person Mori    schedule 31.05.2011
comment
это хороший обходной путь, но на самом деле он не отвечает на мой вопрос. Иногда я хочу проверить 1, или 2, или 10 записей, прежде чем я захочу остановить отладку, поэтому я ищу команду, чтобы остановить отладку для текущего запроса (т. е. разрешить загрузку страницы). Вы знаете о таком? Спасибо! - person Yuval Karmi; 01.06.2011
comment
+1 за «специальное» решение — обязательно посмотрите комментарий. Поскольку вы можете устанавливать переменные для своего кода в целом внутри сеанса отладчика, как если бы это был сеанс irb, это позволит продолжать работу после произвольного количества остановок. - person Matt; 17.06.2011
comment
один исправлен на переменную continue_debugger - в определенных ситуациях он выйдет за рамки, поэтому я пошел дальше и поставил перед ним знак @, чтобы убедиться, что он доступен независимо от области действия. Это самое простое решение! +1 - person Yuval Karmi; 18.06.2011

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

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

person rubysolo    schedule 16.06.2011
comment
Большое спасибо! Хотя это намного чище, я обнаружил, что решение Мори реализуется немного быстрее. Хотел бы я наградить всех здесь щедростью! - person Yuval Karmi; 18.06.2011

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

person Matt    schedule 17.06.2011
comment
СПАСИБО БОЛЬШОЕ за развернутый ответ! Я думаю, что решение Мори немного проще реализовать, но я хотел бы выбрать каждый ответ здесь как правильный. Мы очень ценим ваше время, Мэтт :) - person Yuval Karmi; 18.06.2011

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

debugger unless @no_debug

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

person jcollum    schedule 29.04.2012

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

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

or

  debugger unless !@debug 

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

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

person jcollum    schedule 21.01.2012

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

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

person muirbot    schedule 10.08.2012

Размещаю это здесь в качестве альтернативы, так как этот вопрос появился первым в моих собственных поисках. Допустим, у вас есть фрагмент кода, который не работает при определенных обстоятельствах, но работает в других случаях, и у вас есть множество тестов, которые проверяют этот тест, но один конкретный тест не проходит. Это 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
person Chris Bloom    schedule 27.05.2014

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

eval return

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

person Bret Weinraub    schedule 28.10.2016

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

выйти из всех

вместо

продолжение

Хотя это создаст ошибку, и вам, возможно, придется удалить отладчик и снова отправить запрос, но это избавит вас от всех циклов.

person Sahil Z.    schedule 25.07.2019