我最近注意到 ActiveRecord 对象上的方法 changed?
在 Rails 3.2.13 和 Rails 4.0.1 之间发生了变化。问题在于连接到数据库中整数字段的字段。假设我的模型 Model
带有 number
整数字段:
# Rails 3.2.13
m = Model.last
m.number #=> 5
m.number = '5hello'
m.number #=> 5
m.number_changed? #=> true
m.changed? #=> true
m.changes #=> {:number => [5,5]}
# Rails 4.0.1
m = Model.last
m.number #=> 5
m.number = '5hello'
m.number #=> 5
m.number_changed? #=> false
m.changed? #=> false
m.changes #=> {}
这会导致表单验证出现一些非常恼人的问题——如果用户试图将整数值更改为具有无效字符(但类型转换将导致与初始值相同的值),rails 将不会调用 save
方法,并且不会运行任何验证(包括 numericality: { only_integer: true }
)。
我已经设法通过将 number_changed?
方法覆盖到 super || 来解决这个问题number.to_s != number_before_type_cast
,但这非常难看。
问题是:为什么会发生这种变化?这是错误还是有意更改?如何在不覆盖整数列的所有元方法的情况下修复它?
最佳答案
我不确定您是如何运行验证的,但我的 Rails 应用程序中有一个名为 ExtraField 的模型,并且具有以下验证:
class ExtraField < ActiveRecord::Base
# stuff
validates :display_order, numericality: { only_integer: true }
# more stuff
end
我使用的是 rails 4.0.5,我可以执行以下操作:
e = ExtraField.first
e.display_order #=> 1
e.valid? #=> true
e.errors.messages #=> {}
e.display_order = '1banana'
e.display_order #=> 1
e.display_order_changed? #=> false
e.changed? #=> false
e.valid? #=> false
e.errors.messages #=> {:display_order=>["is not a number"]}
因此,虽然记录确实没有标记为已更改(恕我直言,这似乎是正确的),但我仍然可以运行我的验证并检查模型是否有效。在我看来这不像是一个错误,而只是一个有意的改进。
如果您的表单仅验证模型是否响应 true changed?
,也许您应该检查您的 Controller 代码。或者,如果您使用 gem 来帮助构建表单,我猜它可能是该 gem 中的错误。
关于ruby-on-rails - Rails 3.2.13 与 Rails 4.0.1 - 改变了吗?方法变了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23043346/