Ruby on rails 从生产irb调试到方法
当我查找某个问题时,例如针对特定的ActiveRecord对象,我经常发现自己在生产系统上执行以下操作:Ruby on rails 从生产irb调试到方法,ruby-on-rails,ruby,debugging,irb,byebug,Ruby On Rails,Ruby,Debugging,Irb,Byebug,当我查找某个问题时,例如针对特定的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 `
# 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
[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)
#RAILS_ENV=生产包执行
irb(main)>article=article.find(123)
=> #
irb(主要)>文章。做点什么(3)
NoMethodError:未定义nil:NilClass的方法'id'
有时我无法复制,为什么行文章.dou_something(3)
会抛出错误,所以我想在生产模式下直接在服务器上调试它
现在的问题是:如何使用对象/实例文章上的参数3
进入方法#dou something
当然,可以用这种方法设置一个断点,重新加载生产,让所有客户等待该断点,直到我完成调试。。。但这不是最好的主意
那么,有没有一种方法可以从正在运行的irb/pry会话调试到特定实例的方法中呢?(两者都可以)
在生产服务器中调试是一个可怕的想法。来自PHP世界,我们总是这样做,只有在幸运的情况下有一个数据库备份,事情才会变得异常轰动
相反,您可以做的是设置一个暂存服务器-这将是一个运行在完全相同的平台上、具有完全相同设置的服务器。您甚至可以将cron与pg_backups
结合使用,每天镜像生产数据库,这样您就可以尝试新功能,甚至向协作者展示它们。如果它爆炸了,那就不是世界末日——也没有丢失最终用户数据的风险
<>但是你可能会认为你应该编写测试,而不是使用断点或日志。编写一个复制问题并指定所需行为的测试。然后,您可以使用代码,并从测试状态知道您所做的工作是否正常。您可以使用pry调试器(通过ruby 1.9.3)或pry byebug(ruby>=2)
这两种方法都允许您设置断点,允许您在代码运行时以交互方式单步执行代码,检查变量值、方法返回值等
您将如何使用生产数据进行管理我不太确定,但这将允许您调试特定的方法。您可以将生产上的代码更改为要签入的值\dou something
方法并运行irb
进行检查。因为我们不会重新启动生产服务器,所以不用担心您的更改。在尝试了更多的谷歌搜索之后,我想我找到了一个适合我的解决方案
登录rails控制台/irb/pry会话
设置您的案例(例如,加载您的模型,需要依赖项…),以便您可以在一行中执行要调试的代码
require'byebug'
(或require'debugger'
用于较旧的ruby版本)
现在有趣的部分是:在要调试的行前面放一条调试器语句,如下binding.pry;user.do_某事
或调试器;用户。做点什么
现在您在调试器中。也许你必须用next
跳到下一行(或者如果你启用了快捷方式,就跳到n
)来进入你的方法
以下是我们生产系统的完整示例:
# 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
[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)
[1]撬(主)>需要“byebug”
=>正确
[2] 撬(主)>user=user.find(2)
用户加载(0.3ms)从“用户”中选择“用户”。“用户id”=2限制1
=> #
[3] pry(主)>user.full_名称
NameError:未定义的局部变量或方法地址#
[4] pry(主)>binding.pry;user.full_名称
[68,73]in/usr/src/app/app/models/user.rb
68:完
69:
70:def全名
=>71:“{address.firstname}{address.last_name}”
72:完
73:完
(byebug)
正如我所写,有时您无法在测试或机器上重现错误,有时您必须在生产系统上进行调试。我知道这是个坏主意,但是没有选择余地,我不得不这么做。我们有测试、dev和staging env,但是当bug在生产环境中抛出时,如果您不能在这些环境中重现它,那么这些env就没有多大帮助。所以,在生产环境中调试是最后的选择,这正是我想要避免的。想象一下一个每秒调用数千次的方法,你在其中编写了一些put
语句这就是调试的艺术,您不应该在使用put
时不考虑put
在这个地方,您认为它有问题。如果我听起来像个a-hole,很抱歉,但这里最可能的解释是您忘记在生产中运行迁移。如果您发现很难记住运行迁移(我们都这么做),您可以使用运行rake db:status
的post-commit钩子作为提醒。该错误只是为了演示,不是真正的错误。问题是如何从irb/pry/rails控制台上下文使用调试器进入该方法非常聪明,喜欢!