Rails 3.2到4.0升级:false的未定义方法to_datetime:FalseClass

cmh*_*bbs 7 ruby-on-rails activesupport activemodel ruby-on-rails-3 ruby-on-rails-4

我正在升级我从3.2继承到4.0.1的Rails应用程序.我跟着完了边缘指南:

http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-3-2-to-rails-4-0

除了一个我似乎无法找到根本原因的错误之外,我已经解决了所有问题.当我尝试保存用户模型对象时,我遇到以下错误:

[1] pry(main)> User.create(name: "test user", email: "testuser@frobnitz.com", password: "testPassword123", password_confirmation: "testPassword123")                                                                                                                               

(0.6ms)  BEGIN
(0.9ms)  ROLLBACK
NoMethodError: undefined method `to_datetime' for false:FalseClass
from /home/cmhobbs/src/serve2perform/.gem/ruby/2.3.0/gems/activesupport-4.0.1/lib/active_support/core_ext/date_time/calculations.rb:161:in `<=>'
Run Code Online (Sandbox Code Playgroud)

activesupportrals安装了4.0.1和4.0.1.我使用chgems并清除了我的.gem/目录,Gemfile.lock然后再捆绑.

这是用户模型要点.

这里是所有的回溯输出的,我可以从中获取pry.

以下是User表架构链接.

Bor*_*aMa 7

一旦你发现有问题的回调就是这个:

  before_create :activate_license

  def activate_license
    self.active_license = true
    self.licensed_date = Time.now
  end
Run Code Online (Sandbox Code Playgroud)

事情开始变得更加清晰.这activate_licence是一个回调之前.回调之前,可以通过返回false(或引发异常)来暂停整个回调链.

如果我们在您通过手动添加一些提供的调试输出仔细看puts线到Rails的回调代码中,我们的确可以发现这个回调的比较与假的结果(在这里 -我删除了代码的一些不重要的部分):

result = activate_license
halted = (result == false)
if halted
  halted_callback_hook(":activate_license")
end 
Run Code Online (Sandbox Code Playgroud)

因为返回之前停止回调false(即上面显示的Rails代码)的支持实际上没有从Rails 3.2改为Rails 4.0.1,所以问题必须在于比较本身.

回调返回一个DateTime对象(它也是方法中的最后一个赋值,也是返回的).实际上,DateTimes 的比较在两个Rails版本之间发生了显着变化(同时请注意,==运算符通常使用<=>运算符进行评估):

现在,一切都很清楚:回调的结果(一个DateTime对象)使用<=>运算符与falseRails 4.0进行比较,比较尝试将false对象转换为DateTime没有任何健全性检查,这当然失败并抛出异常.

要解决这个问题,只需确保你的回调返回Rails可以比较的东西false而没有任何问题,例如true,因为你的回调永远不应该停止链:

  def activate_license
    self.active_license = true
    self.licensed_date = Time.now
    true
  end
Run Code Online (Sandbox Code Playgroud)

现在一切都应该按预期工作了.