113

創建has_and_belongs_to_many協會給出下面的如何在工廠女孩

class User < ActiveRecord::Base 
    has_and_belongs_to_many :companies 
end 

class Company < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

你如何定義企業和用戶,包括雙向關聯工廠?這是我嘗試

Factory.define :company do |f| 
    f.users{ |users| [users.association :company]} 
end 

Factory.define :user do |f| 
    f.companies{ |companies| [companies.association :user]} 
end 

現在我嘗試

Factory :user 

也許並不奇怪,這導致一個無限循環爲一體的工廠遞歸使用對方來定義自己。

更令人驚訝的是,我還沒有發現如何在任何地方做到這一點,有沒有一種模式來定義必要的工廠,或者我正在做一些根本性的錯誤?

回答

40

Factorygirl已經更新,現在包括回調來解決這個問題。請參閱http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl瞭解更多信息。

+36

該鏈接實際上沒有說如何處理has_and_belongs_to_many ...我看不到如何做到這一點...... – dmonopoly 2011-07-25 21:16:45

+3

回調語法現在已經改爲:'after(:create)'而不是'after_create'在工廠中女孩在這裏提到:http://stackoverflow.com/questions/15003968/undefined-method-after-create-with-factorygirl – 2014-03-05 07:12:28

0

首先,我強烈建議您使用的has_many:通過替代的habtm(更多關於這here),所以你會喜歡的東西最終會:

Employment belongs_to :users 
Employment belongs_to :companies 

User has_many :employments 
User has_many :companies, :through => :employments 

Company has_many :employments 
Company has_many :users, :through => :employments 

此之後,你就必須的has_many並且可以按照你做的方式在factory_girl中分配給他們。

+3

不應該是'Employment belongs_to:user'和'Employment belongs_to:company'這個連接模式將一個公司與一個用戶連接起來嗎? – 2010-06-15 11:00:31

+5

我通過快速瀏覽你提到的帖子得出的結論是,它取決於你的用例是否選擇habtm或has_many:through。沒有真正的「勝利者」。 – auralbee 2011-03-03 17:02:30

+0

那麼,使用hmt時唯一的開銷就是你必須在直通表上定義id。現在,我無法想象一個可能導致任何問題的情況。我沒有說habtm是沒有用的,只是在99%的用例中,使用hmt更有意義(因爲它的優點)。 – 2011-03-08 21:49:40

5

對我來說有效的是在使用工廠時設置關聯。 使用你的例子:

user = Factory(:user) 
company = Factory(:company) 

company.users << user 
company.save! 
9

我couldn't找到所提供的網站上的上述情況的一個例子。 (只有1:N和多態協會,但沒有habtm)。我也有類似的情況,我的代碼如下所示:

Factory.define :user do |user| 
user.name "Foo Bar" 
user.after_create { |u| Factory(:company, :users => [u]) } 
end 

Factory.define :company do |c| 
c.name "Acme" 
end 
+3

如果驗證非零用戶數呢? – dfens 2011-06-07 14:27:23

22

在我看來,只要創建兩個不同的工廠,如:

 
Factory.define :user, :class => User do |u| 
    # Just normal attributes initialization 
end 

Factory.define :company, :class => Company do |u| 
    # Just normal attributes initialization 
end 

當你寫的測試用例的用戶則只是寫像這

 
Factory(:user, :companies => [Factory(:company)]) 

希望它會工作。

+2

謝謝這是我能夠工作的唯一例子。工廠女孩是habtm的大頭痛。 – jspooner 2011-08-01 23:55:47

+0

這不再適用於最近版本的FactoryGirl(我在想Rails 3) – Raf 2012-11-08 14:59:11

3
factory :company_with_users, parent: :company do 

    ignore do 
     users_count 20 
    end 

    after_create do |company, evaluator| 
     FactoryGirl.create_list(:user, evaluator.users_count, users: [user]) 
    end 

    end 

警告:更改用戶:[用戶]到:用戶=> [用戶]對Ruby 1.8.x的

+3

不應該是: 'after_create {| company,evaluator | FactoryGirl.create_list(:user,evaluator.users_count,companies:[company]) }' ? – Raf 2012-11-08 14:56:06

120

這裏是爲我工作的解決方案。

FactoryGirl.define do 

    factory :company do 
    #company attributes 
    end 

    factory :user do 
    companies {[FactoryGirl.create(:company)]} 
    #user attributes 
    end 

end 

,如果你需要特定的公司,你可以使用工廠這樣

company = FactoryGirl.create(:company, #{company attributes}) 
user = FactoryGirl.create(:user, :companies => [company]) 

希望這將是爲某人有幫助。

+4

謝謝你,最整齊的解決方案。 – 2012-05-29 19:14:56

+0

謝謝。經過數小時的沮喪,這已經解決了我的問題。 – 2012-10-08 17:26:01

+0

這隻適用於所有工廠都在*一個文件*的情況,這是非常不可取的。因此下面@opsb提到的解決方案似乎更好。 – spier 2013-08-02 09:36:02

1

找到這樣好的和冗長:

FactoryGirl.define do 
    factory :foo do 
    name "Foo" 
    end 

    factory :bar do 
    name "Bar" 
    foos { |a| [a.association(:foo)] } 
    end 
end 
0

更新爲Rails 5:

使用has_and_belongs_to_many協會相反的,你應該考慮:has_many :through關聯。

用戶工廠,對這個關聯是這樣的:

FactoryBot.define do 
    factory :user do 
    # user attributes 

    factory :user_with_companies do 
     transient do 
     companies_count 10 # default number 
     end 

     after(:create) do |user, evaluator| 
     create_list(:companies, evaluator.companies_count, user: user) 
     end 
    end 
    end 
end 

您可以用類似的方式創建公司的工廠。

一旦兩個工廠都已設置,您可以使用companies_count option創建user_with_companies工廠。您可以在此指定用戶所屬的公司數:create(:user_with_companies, companies_count: 15)

您可以找到有關factory girl associations here的詳細說明。