How to create has_and_belongs_to_many associations in Factory girl
Solution 1
Factorygirl has since been updated and now includes callbacks to solve this problem. Take a look at http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl for more info.
Solution 2
Here is the solution that works for me.
FactoryGirl.define do
factory :company do
#company attributes
end
factory :user do
companies {[FactoryGirl.create(:company)]}
#user attributes
end
end
if you will need specific company you can use factory this way
company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])
Hope this will be helpful for somebody.
Solution 3
In my opinion, Just create two different factories like:
Factory.define :user, :class => User do |u| # Just normal attributes initialization end Factory.define :company, :class => Company do |u| # Just normal attributes initialization end
When you write the test-cases for user then just write like this
Factory(:user, :companies => [Factory(:company)])
Hope it will work.
Solution 4
I couldn´t find an example for the above mentioned case on the provided website. (Only 1:N and polymorphic assocations, but no habtm). I had a similar case and my code looks like this:
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
Solution 5
What worked for me was setting the association when using the factory. Using your example:
user = Factory(:user)
company = Factory(:company)
company.users << user
company.save!
opsb
Updated on July 26, 2020Comments
-
opsb almost 4 years
Given the following
class User < ActiveRecord::Base has_and_belongs_to_many :companies end class Company < ActiveRecord::Base has_and_belongs_to_many :users end
how do you define factories for companies and users including the bidirectional association? Here's my attempt
Factory.define :company do |f| f.users{ |users| [users.association :company]} end Factory.define :user do |f| f.companies{ |companies| [companies.association :user]} end
now I try
Factory :user
Perhaps unsurprisingly this results in an infinite loop as the factories recursively use each other to define themselves.
More surprisingly I haven't found a mention of how to do this anywhere, is there a pattern for defining the necessary factories or I am doing something fundamentally wrong?
-
Daniel Beardsley about 14 yearsShouldn't that be
Employment belongs_to :user
andEmployment belongs_to :company
with the join model connecting one Company with one User? -
auralbee over 13 yearsMy conclusion from a quick read through the post you mentioned is that it depends on your use case whether to choose habtm or has_many :through. There is no real "winner".
-
Milan Novota over 13 yearsWell, the only overhead when using hmt is that you have to have id defined on the through table. Right now, I can't imagine a situation when that could cause any problem. I don't say that habtm is of no use, just that in 99% use cases it makes more sense to use hmt (because of its advantages).
-
dfens about 13 yearswhat if there is validation of non-zero user count ?
-
dmonopoly almost 13 yearsThe link doesn't actually say how to handle has_and_belongs_to_many... I don't see how to do this...
-
blakkheartt12 almost 13 yearsThanks this is the only example I could get working. Factory girl is a big headache for habtm.
-
Mik about 12 yearsThank you, most neat of all solutions.
-
sbeam about 12 years-1, just because HMT has more 'advantages' only means you should use it if you NEED those advantages. Pet peeve, because I'm working on a project now where the developer used HMT in several cases where HABTM would have sufficed. The codebase is therefore larger, more complex, less intuitive and produces slower SQL joins because of it. So, use HABTM when you can, then when you NEED to create a separate join model to store extra info about each association, only then use HMT.
-
Tony Beninate over 11 yearsThank you. This has fixed my problem after hours of frustration.
-
Raf over 11 yearsShouldn't it be :
after_create { |company, evaluator| FactoryGirl.create_list(:user, evaluator.users_count, companies: [company]) }
? -
Raf over 11 yearsThis no longer works with recent versions of FactoryGirl (i'm thinking Rails 3)
-
spier almost 11 yearsThis only works for me when all the factories are in one file which is quite undesirable. Therefore the solution mentioned by @opsb below seems to be better.
-
Michael Yagudaev over 10 yearsCallback syntax has now been changed to:
after(:create)
instead ofafter_create
in factory girl as mentioned here: stackoverflow.com/questions/15003968/… -
monteirobrena about 6 years
foos { |a| [a.association(:foo)] }
helps me a lot! Thank you!