我有两个具有以下结构的模型:
class Wallet < ActiveRecord::Base
include ActiveModel::Validations
has_one :credit_card
accepts_nested_attributes_for :credit_card
validates :credit_card, :presence => true
validates_associated :credit_card
...
end
class CreditCard < ActiveRecord::Base
include ActiveModel::Validations
belongs_to :wallet
validates :card_number, :presence => true
validates :expiration_date, :presence => true
...
end
我正在使用RSpec测试我的应用程序的功能,我注意到一些奇怪的东西。如果我创建一个Hash,其属性不符合我的嵌套模型的验证标准(例如有一个nil card_number),然后尝试进行update_attributes
调用,那么我在Wallet对象中返回的内容使用无效的CreditCard嵌套模型以及相应的错误。这是正确的预期行为。
如果我采用相同的Hash并运行assign_attributes
,然后运行save
(这就是update_attributes应该做的所有事情),那么我将返回一个带有完全nil嵌套对象的无效Wallet对象。为什么会这样?如何更新所有嵌套属性值并检查错误而不保存?
答案 0 :(得分:4)
首先 - 您不需要include ActiveModel::Validations
,因为它们带有ActiveRecord::Base
。
第二 - 是update_attributes
在内部使用assign_attributes
所以基本上它应该按预期工作。
如果您没有attr_accessible
,attr_protected
,with/without_protection
选项,我认为您正在使用
{'credit_card_attributes' => {'card_number' => ''}}
然后它看起来像rails中的某种bug。但与此同时我只是检查它,似乎它工作正常。
如上所述,如果您只想检查验证而不在测试中保存对象,那么只需运行
即可Wallet.new(hash_with_attributes).valid?
它应该返回正确的钱包对象,其中包含嵌套的credit_card和错误。
答案 1 :(得分:1)
听起来像Strong Params(Rails 4功能)可能会剥离嵌套属性,因为没有它们你的验证失败,你会被重定向回编辑页面并出现错误,你的信用卡nested_attributes现在为零。
也许这会有所帮助。 https://stackoverflow.com/a/17532811/793330
另外save和update_attributes不是一回事。保存将保存整个对象,而更新只会更改您传递给它的已更改的项目。略有差异,但差异不小。
答案 2 :(得分:0)
据我了解,assign_attributes会跳过安全检查。
In Rails 3, is there a difference between = and assign_attributes?