4

当我寻找问题时,例如使用特定的 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的参数进入方法?3article

当然,可以在该方法中设置断点,重新加载生产并让所有客户在该断点上等待,直到我完成调试......但这不是最好的主意。

那么,有没有办法从正在运行的 irb / pry 会话中调试到特定实例的方法?(两者都可以)

4

3 回答 3

8

在尝试了更多的谷歌搜索之后,我想我找到了一个适合我的解决方案。

  1. 登录到您的 Rails 控制台/irb/pry 会话
  2. 设置您的案例(例如加载您的模型,需要依赖项......),以便您可以在一行中执行要调试的代码
  3. require 'byebug'(或require 'debugger'旧的 ruby​​ 版本)
  4. 现在有趣的部分:在你想调试的行前面放一个调试器语句,binding.pry; user.do_something或者debugger; user.do_something
  5. 现在你在你的调试器中。也许您必须跳到下一行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) 
于 2016-04-21T07:03:44.657 回答
0

在生产服务器中调试是一个可怕的想法。来自 PHP 世界,我们过去一直这样做,事情会爆炸性地发生,只有当你幸运的是有数据库备份时。

相反,您可以做的是设置一个登台服务器 - 这将是一个在完全相同的平台上运行并具有完全相同的设置的服务器。您甚至可以pg_backups每天使用 cron 来镜像生产数据库,以便您可以尝试新功能,甚至向合作者展示它们。如果它爆炸了,那么它不是世界末日——而且没有丢失最终用户数据的风险。

但是您可能会认为您实际上应该编写测试而不是使用断点或日志。编写一个复制问题并指定所需行为的测试。然后,您可以使用代码并从测试状态中知道您正在做的事情是否有效。

于 2016-04-20T15:06:30.113 回答
-2

您可以使用 pry-debugger(通过 ruby​​ 1.9.3)或 pry-byebug(Ruby >= 2)。

这两者都允许您设置断点,允许您在代码运行时以交互方式单步执行代码、检查变量值、方法返回值等。

您将如何使用生产数据进行管理我不太确定,但这将允许您调试特定的方法。

于 2016-04-20T15:30:27.960 回答