Отладка в метод из производства IRB
Когда я ищу проблему, например, с конкретным объектом ActiveRecord, я часто обнаруживаю, что выполняю в своей производственной системе следующее:
# RAILS_ENV=production bundle exec
irb(main)> article = Article.find(123)
=> #<Article id: 123, title: "Foobar">
irb(main)> article.do_something(3)
NoMethodError: undefined method `id' for nil:NilClass
Иногда я не могу воспроизвести, почему линия article.do_something(3)
выдает ошибку, поэтому я хочу отладить ее прямо на моем сервере, в производственном режиме.
Проблема сейчас в следующем: как мне войти в метод #do_something
с аргументом 3
на объекте / экземпляре article
?
Конечно, в этом методе можно установить точку останова, перезагрузить производство и позволить всем своим клиентам подождать на этой точке останова, пока я не закончу отладку... Но это не лучшая идея.
Итак, есть ли способ отладки в методе конкретного экземпляра из запущенного сеанса irb / pry? (оба были бы в порядке)
6 ответов
После того, как я попробовал все больше и больше гуглить, я думаю, что нашел решение, которое работает для меня.
- Войдите в вашу консоль rails console / irb / pry session
- Настройте ваш случай (например, загрузите ваши модели, требуйте зависимостей...), чтобы вы могли выполнить код, который вы хотите отлаживать, в одну строку
require 'byebug'
(или жеrequire 'debugger'
для старых версий ruby)- Теперь интересная часть: поместите оператор отладчика перед строкой, которую вы хотите отлаживать, вот так
binding.pry; user.do_something
или жеdebugger; user.do_something
- Теперь вы в своем отладчике. Может быть, вам нужно перейти к следующей строке с
next
(или простоn
если у вас включены ярлыки), чтобы перейти к вашему методу.
Вот полный пример из нашей производственной системы:
[1] pry(main)> require 'byebug'
=> true
[2] pry(main)> user = User.find(2)
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
=> #<User id: 2, name="XXX XXX">
[3] pry(main)> user.full_name
NameError: undefined local variable or method address for #<User:0x0055b168663590>
[4] pry(main)> binding.pry; user.full_name
[68, 73] in /usr/src/app/app/models/user.rb
68: end
69:
70: def full_name
=> 71: "#{address.firstname} #{address.last_name}"
72: end
73: end
(byebug)
Конечно, pry, byebug и т. д. — это круто, НО вам не нужна жемчужина.
Ruby 3 (и более новые версии Ruby 2.x) имеет встроенную отладку irb.
require 'irb'
def run
a = "hello"
binding.irb # debug starts here, eg puts a
a = "something else"
a
end
run
Отладка на вашем рабочем сервере - ужасная идея. Исходя из мира PHP, мы привыкли делать это все время, и все будет впечатляюще, и только если вам повезет, будет резервная копия базы данных.
Вместо этого вы можете настроить промежуточный сервер - это сервер, работающий на той же платформе с точно такими же настройками. Вы можете даже использовать cron вместе с pg_backups
ежедневно зеркалировать производственную базу данных, чтобы вы могли опробовать новые функции и даже показать их сотрудникам. И если он взорвется, то это не конец света - и нет риска потери данных конечного пользователя.
Но вы можете подумать, что на самом деле вы должны писать тесты, а не использовать точки останова или журналы. Напишите тест, который повторяет проблему и определяет желаемое поведение. Затем вы можете поиграть с кодом и узнать из состояния теста, работает ли то, что вы делаете.
Вы можете использовать pry-debugger (через ruby 1.9.3) или pry-byebug (Ruby >= 2).
Оба из них позволяют вам устанавливать точки останова, позволяя в интерактивном режиме выполнять пошаговый просмотр кода, проверять значения переменных, возвращаемые значения методов и т. Д.
Как вы справитесь с производственными данными, я не совсем уверен, но это позволит вам отлаживать определенный метод.
Вы можете изменить код на вашем производстве, чтобы поставить значение, которое вы хотите проверить в #do_something
метод и бег irb
проверить это. Потому что мы не перезагружаем производственный сервер, поэтому не беспокойтесь о ваших изменениях.
Вы можете пойти простым путем, и попробуйте сделать отладку через puts
, Вы можете добавить как можно больше puts
внутри вашего метода, как вам нужно, перед каждой возможной строкой может возникнуть проблема