Complete FactoryGirl association with multiple models

I am trying to figure out how to write a factory that belongs to two different models, each of which must have the same parent model. Here's a contrived code example:

class User < ActiveRecord::Base has_many :widgets has_many :suppliers attr_accessible :username end class Widget < ActiveRecord::Base belongs_to :user has_many :parts attr_accessible :name end class Supplier < ActiveRecord::Base belongs_to :user has_many :parts attr_accessible :name end class Part < ActiveRecord::Base belongs_to :supplier belongs_to :widget attr_accessible :name end 

Here is what I still have:

 factory :user do name 'foo' end factory :widget do association :user name 'widget' end factory :supplier do association :user name 'supplier' end factory :part do association :widget association :supplier name 'part' end 

The problem is that part.widget.user != part.supplier.user and they should be the same.

I tried the following without success:

 factory :part do association :widget association :supplier, user: widget.user name 'part' end 

Any suggestions? Or do I need to change it after creating the part?

thanks

+6
source share
2 answers

I believe you can do this with callback :

 factory :part do association :widget association :supplier name 'part' after(:create) do |part| user = FactoryGirl.create(:user) part.widget.user = part.supplier.user = user end end 

See also: Get two associations inside Factory to share another association.

+7
source

Another option is to use transition variables to allow the transfer of the associated object.

I usually use two variables:

  • A variable containing the association to be used in the factory
  • A boolean indicating whether to generate a default value for an association variable - perhaps not necessary in your particular case, but it can be very useful

Here's what it would look like:

 factory :part do transient do # this variable is so we can specify the user with_user { no_user ? nil : Factory.create(:user) } # this variable allows the user to be nil no_user false end # The transient variable for_user can now be used to create the # associations for this factory widget { Factory.create(:widget, :user => with_user) } supplier { Factory.create(:supplier, :user => with_user) } name 'part' end 

Then it can be used in the following ways:

 # use the default user part = Factory.create :part part.widget.user.should == part.supplier.user # use a custom created user user = Factory.create :user, :name => 'Custom user' part = Factory.create :part, for_user: user part.widget.user.should == user part.supplier.user.should == user # create a part without any user # (again this probably isn't need in your specific case, but I have # found it a useful pattern) part = Factory.create :part, no_user: true part.widget.user.should be_nil part.supplier.user.should be_nil 
0
source

All Articles