Rails“assign_attributes”不分配嵌套模型

时间:2013-04-13 02:05:53

标签: ruby-on-rails ruby-on-rails-3 validation nested-attributes

我有两个具有以下结构的模型:

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对象。为什么会这样?如何更新所有嵌套属性值并检查错误而不保存?

3 个答案:

答案 0 :(得分:4)

首先 - 您不需要include ActiveModel::Validations,因为它们带有ActiveRecord::Base

第二 - 是update_attributes在内部使用assign_attributes所以基本上它应该按预期工作。

如果您没有attr_accessibleattr_protectedwith/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?