2

私のモデル関係のような

class Cart < ActiveRecord::Base
  has_many :cart_items, :inverse_of => :cart, :dependent => :destroy
  accepts_nested_attributes_for :cart_items, :allow_destroy => :true, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
  validates_associated :cart_items
  validates :cart_name, :presence => {:message => "Must be filled" }
end

class CartItem < ActiveRecord::Base
  belongs_to :cart, :inverse_of => :cart_items
  validates :cart_item_no, :presence => {:message => "Must be filled"}, :uniqueness => {:message => "Already exists" }
end

factory.rb

FactoryGirl.define do
  factory :cart do
    cart_name "sample"
    factory :cart_with_cart_items do
      after(:build) {|cart|
        2.times { cart.cart_items.build(attributes_for(:cart_item)) }
      }
      after(:create) {|cart|
        cart.cart_items.each {|cart_item| cart_item.save! }
      }
    end
  end

  factory :cart_item  do
    cart_item_no 1
    cart
  end
end

以下のテストケースは常に失敗します

it "should not be valid with same cart_id" do
  cart = FactoryGirl.build(:cart_with_cart_items)
  cart.should_not be_valid
end

次に、コンソールで調査し、以下のコードの例で、 cart_itemsで同じ *cart_item_no* を 2 回使用して常に true を返す検証を行います。

cart = Cart.new(:cart_name => "yyy")
  => #<Cart id: nil, cart_name: "yyy">
2.times { cart.cart_items.build(:cart_item_no => 1000) }
  => 2
cart.cart_items 
  => [#<CartItem id: nil, cart_item_no: 1000>, #<CartItem id: nil, cart_item_no: 1000>]
cart.valid?
  => true
cart.save!
  => true  

これはレールの問題ですか?

テストケースを解決するには?

4

1 に答える 1

0

一意性の検証は、データベースに対してのみチェックします。あなたの場合、cart_items互いに競合するがデータベース内のレコードとは競合しない2つがあるため、個別に両方とも有効です。これが、検証に合格する理由です。

クラスにカスタム検証を追加できますCart(テストされていません)。

validates :unique_cart_items

def unique_cart_items
  unless cart_items.collect(&:cart_item_no).uniq.size < cart_items.size
    # set some error attribute here
  end
end

cart_item_noこれにより、一意の値の数がの数と比較されますcart_items。それらが同じでない場合は、重複していcart_item_noます。

于 2012-12-13T13:41:38.673 に答える