我正在升级我从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 `<=>'
activesupport
安装了4.0.1和rals
4.0.1。我使用chgems并且在再次捆绑之前清除了我的.gem/
目录和Gemfile.lock
。
here is all of the backtrace output我可以从pry
获得。
答案 0 :(得分:7)
一旦你发现有问题的回调就是这个:
before_create :activate_license
def activate_license
self.active_license = true
self.licensed_date = Time.now
end
事情开始变得更加清晰。 activate_licence
是之前的回调。 之前回调可以halt the whole callbacks chain by returning false
(或引发异常)。
如果我们通过在Rails回调代码中手动添加一些puts
行来仔细查看您提供的调试输出,我们确实可以找到此回调结果与false(here - I的比较删除了一些不重要的代码部分):
result = activate_license
halted = (result == false)
if halted
halted_callback_hook(":activate_license")
end
因为通过返回false
(即上面显示的Rails代码)回调之前停止支持实际上没有从Rails 3.2更改为Rails 4.0.1,所以问题必须在于比较本身
回调返回一个DateTime
对象(它也是方法中的最后一个赋值,也是返回的)。实际上,DateTime
的比较在两个Rails版本之间发生了显着变化(同时请注意==
运算符通常是evaluated using the <=>
operator):
是this:
def <=>(other)
if other.kind_of?(Infinity)
super
elsif other.respond_to? :to_datetime
super other.to_datetime
else
nil
end
end
特别注意respond_to?
检查other
对象是否也是日期或时间对象,否则返回nil
。
而在Rails 4.0.1中,changed to下面的代码为<{3}}:
def <=>(other)
super other.to_datetime
end
→所有完整性检查都已消失!
现在,一切都很清楚:使用DateTime
运算符和<=>
比较回调的结果(false
对象),并且在Rails 4.0下,比较尝试转换false
DateTime
对false
没有任何健全性检查,当然会失败并抛出异常。
要解决此问题,只需确保您的回调返回Rails可以与true
进行比较而没有任何问题的内容,例如: def activate_license
self.active_license = true
self.licensed_date = Time.now
true
end
,因为你的回调永远不应该停止链:
start = '2012-04-23'
end = '2013-01-23'
>>> pd.DatetimeIndex([pd.datetime(ts.year, ts.month, int(end.split("-")[-1]))
for ts in pd.date_range(start, end, freq='BM')])
DatetimeIndex(['2012-04-23', '2012-05-23', '2012-06-23', '2012-07-23', '2012-08-23', '2012-09-23', '2012-10-23', '2012-11-23', '2012-12-23'], dtype='datetime64[ns]', freq=None)
现在一切都应该按照预期再次发挥作用。
答案 1 :(得分:3)
你甚至可以在核心类中绑定,请执行类似的操作并查看other
的内容,来自何处。
/home/cmhobbs/src/serve2perform/.gem/ruby/2.3.0/gems/activesupport-4.0.1/lib/active_support/core_ext/date_time/calculations.rb
def <=>(other)
binding.pry
if other.kind_of?(Infinity)
super
elsif other.respond_to? :to_datetime
super other.to_datetime rescue nil
else
nil
end
end