6

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

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 测试我的应用程序的功能,我注意到一些奇怪的东西。如果我创建一个属性不符合嵌套模型验证条件的哈希(例如具有 nil card_number),然后尝试进行update_attributes调用,那么我在 Wallet 对象中返回的内容包含无效的 CreditCard 嵌套模型和相应的错误。这是正确的、预期的行为。

如果我采用相同的 Hash 并运行assign_attributes,然后save(这就是 update_attributes 应该做的所有事情,那么我会返回一个无效的 Wallet 对象,其中包含一个完全为零的嵌套对象。为什么会这样?我怎样才能更新所有嵌套的对象属性值并检查错误而不保存?

4

3 回答 3

4

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

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

如果您没有任何attr_accessible, attr_protected,with/without_protection选项,我假设您正在创建正确的哈希

{'credit_card_attributes' => {'card_number' => ''}}

那么它看起来像是rails中的某种错误。但同时我也只是检查了一下,似乎它工作正常。

除此之外,如果您只想检查验证而不在测试中保存对象,那么只需运行

Wallet.new(hash_with_attributes).valid?

它应该返回正确的钱包对象,其中包含嵌套的 credit_card 和错误。

于 2013-04-15T12:34:17.510 回答
2

在我看来,Strong Params(Rails 4 功能)可能正在剥离嵌套属性,并且由于没有它们您的验证失败,您将被重定向回编辑页面并出现错误,并且您的信用卡 nested_attributes 现在为零。

也许这会有所帮助。https://stackoverflow.com/a/17532811/793330

save 和 update_attributes 也不是一回事。Save 将保存整个对象,而 update 只会更改您传递给它的已更改的项目。有细微的差别,但还是有差别的。

于 2014-02-08T23:50:13.677 回答
0

据我了解,assign_attributes 跳过了安全检查。

在 Rails 3 中,= 和 assign_attributes 有区别吗?

于 2013-04-13T02:54:58.090 回答