2014-04-20 70 views
0

我遇到了一個問題,FactoryGirl似乎是用has_many關係創建額外記錄。FactoryGirl使用has_many關聯創建額外記錄

鑑於這些機型:

class NextAction < ActiveRecord::Base 
    has_many :next_actions_orders 
    has_many :orders, through: :next_actions_orders 
end 

class NextActionsOrder < ActiveRecord::Base 
    belongs_to :order 
    belongs_to :next_action 
end 

class Order < ActiveRecord::Base 
    has_many :next_actions_orders 
    has_many :next_actions, through: :next_actions_orders 
end 

而且這些工廠:

FactoryGirl.define do 
    factory :next_action do 
    status :pending 

    trait :pickup do 
     next_actions_orders { FactoryGirl.create_list(:next_actions_order, 1) } 
     action_type :pickup 
    end 

    trait :multiple_pickups do 
     next_actions_orders { FactoryGirl.create_pair(:next_actions_order) } 
     action_type :pickup 
    end 
    end 
end 

FactoryGirl.define do 
    factory :next_actions_order do 
    order { FactoryGirl.create(:order) } 
    next_action 
    end 
end 

FactoryGirl.define do 
    factory :order do 
    status :pending 
    end 
end 

正如你可以下個動作廠看到,我遇到了一個問題,建立NextActionOrder關聯。

我通常會使用next_actions_orders { FactoryGirl.create(:next_actions_order) }has_many :next_actions_orders,我得到undefined method 'each' for #<NextActionsOrder...錯誤。

next_actions_orders { FactoryGirl.create_list(:next_actions_order, 1) }似乎是一種解決方法。如下所示,這似乎不是問題的原因,因爲它也存在於create_pair示例中。

真正的問題是這樣的:

it 'create_list generates duplicate FactoryGirl records' do 
    puts NextAction.count # output: 0 

    pickup = create(:next_action, :pickup) 

    puts NextAction.count # output: 2 

    ## binding.pry 
end 

簡潔地說,在create(:next_action)電話似乎產生1個額外個動作記錄比是必需的。

我用pry來檢查這個,果然,你可以看到這個。

與上面示出的第一位置插入撬,查詢產生以下:

pry(#<RSpec::Core::ExampleGroup::Nested_1>)> NextAction.all 
=> [#<NextAction id: 2, ... created_at: "2014-04-20 16:40:57", updated_at: "2014-04-20 16:40:57", status: 0>, 
#<NextAction id: 3, ... created_at: "2014-04-20 16:40:57", updated_at: "2014-04-20 16:40:57", status: 0>] 
pry(#<RSpec::Core::ExampleGroup::Nested_1>)> NextActionsOrder.all 
=> [#<NextActionsOrder id: 1, next_action_id: 3, order_id: 2>] 
pry(#<RSpec::Core::ExampleGroup::Nested_1>)> Order.all 
=> [#<Order id: 2, created_at: "2014-04-20 16:40:57", updated_at: "2014-04-20 16:40:57", status: 0>] 

在這裏,一切看起來很大,除了個動作ID#2。它沒有關聯到任何地方,它只是由於某種原因創建的孤兒記錄。

這裏與create_pair會發生什麼:

it 'create_pair generates duplicate FactoryGirl records' do 
    puts NextAction.count # output: 0 

    pickups = create(:next_action, :multiple_pickups) 

    puts NextAction.count # output: 3 

    ## binding.pry 
end 

用撬插入如圖所示,同樣的疑問產生:

pry(#<RSpec::Core::ExampleGroup::Nested_1>)> NextAction.all 
=> [#<NextAction id: 4, created_at: "2014-04-20 16:53:20", updated_at: "2014-04-20 16:53:20", status: 0>, 
#<NextAction id: 5, created_at: "2014-04-20 16:53:20", updated_at: "2014-04-20 16:53:20", status: 0>, 
#<NextAction id: 6, created_at: "2014-04-20 16:53:20", updated_at: "2014-04-20 16:53:20", status: 0>] 
pry(#<RSpec::Core::ExampleGroup::Nested_1>)> NextActionsOrder.all 
=> [#<NextActionsOrder id: 2, next_action_id: 6, order_id: 3>, 
#<NextActionsOrder id: 3, next_action_id: 6, order_id: 4>] 
pry(#<RSpec::Core::ExampleGroup::Nested_1>)> Order.all 
=> [#<Order id: 3, created_at: "2014-04-20 16:53:20", updated_at: "2014-04-20 16:53:20", status: 0>, 
#<Order id: 4, created_at: "2014-04-20 16:53:20", updated_at: "2014-04-20 16:53:20", status: 0>] 

再次,一切看起來不錯,但現在我們有2個孤兒個動作記錄 - ID#4和#5。

任何想法?非常感謝!

回答

1

這是因爲在工廠next_action的:next_actions_order,從而產生額外的next_action ...

我會重寫使用

after(:build) do |next_action, evaluator| 
    next_action.orders << build(:order) 
end 

after(:build) do |next_action, evaluator| 
    next_action.orders << build_list(:order, evaluator.orders_count) 
end 

如果next_action廠你需要不止一個。

這樣一來,整個鏈條就會立即創建,所有交叉引用都應該填充! (並且沒有雙打!)

+0

非常好,謝謝,那工作!出於某種原因,我認爲next_action協會是必要的,但顯然不是。我最終做了'(1 ..evaluateator.orders_count).to_a.each {next_action.orders << build(:order)}'這樣我就可以處理需要多個訂單的情況。 – shedd

+1

有一個更好的方法來做到這一點:看到我添加到我的答案的第二個選項! – Danny

+0

謝謝你幫我清理乾淨! – shedd