Sale
属于Item
和Price
。 Item
属于Item_Type
,而Price
也属于ItemType
。对于任何Sale
s
,我们应该有s.item.item_type == s.price.item_type
,否则数据库处于无效状态。此外,Sale validates_presence_of :item, :price
。
我想使用FactoryBot构建Sale
实例。
FactoryBot.define do
sequence :item_type_name do |n|
"type#{n}"
end
factory :item_type do
name {generate(:item_type_name)}
end
factory :item
item_type
end
factory :price do
item_type
end
factory :sale do
item
price
end
end
sale = build(:sale)
问题:这产生了冲突的item_types
sale.item.item_type != sale.price.item_type
尝试修复:
factory :sale do
item
price
after(:build) do |sale|
if (sale.item.item_type != sale.price.item_type)
sale.price = build(:price, item_type: sale.item.item_type)
end
end
end
当您建立没有覆盖的销售时,这可以正常工作
sale = build(:sale)
但是当提供price
替代但没有提供item
时却给出了不良行为:
myPrice = build(:price)
sale = build(:sale, price: myPrice) # oops! myPrice is overwritten
所需的行为如下
describe 'sale_factory' do
context 'no overrides provided' do
it 'makes an item and price with matching item_types' do
sale = build(:sale)
expect(sale.item.item_type).to eq sale.price.item_type
end
end
context 'item override provided' do
it 'makes a price whose item_type matches that of item override' do
item = build(:item)
sale = build(:sale, item: item)
expect(sale.item).to eq item
expect(sale.price.item_type).to eq item.item_type
end
context 'price override provided' do
it 'makes an item whose item_type matches that of price override' do
price = build(:price)
sale = build(:sale, price: price)
expect(sale.price).to eq price
expect(sale.item.item_type).to eq price.item_type
end
context 'price and item overrides provided' do
it 'makes a sale using provided overrides if item_types do not conflict' do
item = build(:item)
price = build(:price, item_type: item.item_type)
sale = build(:sale, item: item, price: price)
expect(sale.item).to eq item
expect(sale.price).to eq price
end
it 'raises an error if item_types conflict' do
item_type_1 = build(:item_type)
item_type_2 = build(:item_type)
item = build(:item, item_type: item_type_1)
price = build(:price, item_type: item_type_2)
expect{build(:sale, item: item, price: price)}
.to raise_error "conflicting item types"
end
end
end
如何实现所需的行为?