How to specify traits for model associations in FactoryGirl

If you’re using RSpec and FactoryGirl to automate testing for your Rails app, you probably know that when creating a factory for a model that has association you can simply specify the factory of the associated model. For example, suppose your Contact model has associations with Phone and Store models:

FactoryGirl.define do factory :contact do |f| f.name { Faker::Name.name } phone store end end

And you probably know you can have traits for factories, for example, different settings for different types of stores:

FactoryGirl.define do 
  factory :store do |f| 
    after(:create) { |store| 
      store.update_attributes :name => Faker::Name.last_name + " LLC" 
    } 

    trait :unknown do 
      after(:build) { |store| store.init_blank(Settings.feature_set_unknown) } 
    end 

    trait :restaurant do 
      after(:build) { |store| store.init_blank(Settings.feature_set_restaurant) } 
    end 

    trait :retailer do 
      after(:build) { |store| store.init_blank(Settings.feature_set_retailer) } 
    end 
  end
end

However, what we could not find documented anywhere was how to specify a trait for an associations. Say when you create a contact factory you want specify which type of store that contact belongs to:

Here’s the magic decoder ring… use
:factory => [:association_factory_name, :trait_name]

FactoryGirl.define do 
  factory :contact do |f| 
    f.name { Faker::Name.name } 
    phone association :store, :factory => [:store, :unknown] 

    trait :foodie_contact do 
      association :store, :factory => [:store, :restaurant] 
    end 

    trait :retailer_contact do 
      association :store, :factory => [:store, :retailer] 
    end 
  end 
end

Which you can then invoke as follows in your examples:

c = FactoryGirl.create(:contact, :retailer_contact)

Leave a Reply

Your email address will not be published. Required fields are marked *