Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

factory girl nested factory

I have an account model that belongs_to a role model.

factory :role do
  name "student"
end

factory :account do
  user
  role
end

The first factory creates a role named "student". The second factory creates an account that is associated to the student role that was created in the previous factory. It also is associated with a user...which is not important for this question.

I have many roles to be tested (admin, student, assistant)... I dont want to specify 'student' in the role factory...thats too static. How do I specify what role to create at the time the account factory is created? Like:

  factory :account do
    user
    role_id { factory :role { name: "admin"} }
  end

What is the best way to accomplish this?

like image 234
hellion Avatar asked Dec 30 '12 18:12

hellion


1 Answers

If you want a purely FG solution, you could use Traits:

factory :account do
  user

  trait :student do
    association :role, :name => "student"
  end

  trait :admin do
    association :role, :name => "admin"
  end
end

FactoryGirl.create :account, :student
FactoryGirl.create :account, :admin

However, you can override the properties of the factory when you create the factory object. This allows for more flexibility:

FactoryGirl.create(:account,
  :role => FactoryGirl.create(:role, :name => "student")
)

Since this is obviously verbose, I'd create a little helper method:

def account_as(role, options = {})
  FactoryGirl.create(:account,
    options.merge(:role => FactoryGirl.create(:role, :name => "student"))
  )
end

Then in your tests:

let(:account) { account_as "student" }

Alternately, you could just shorten up your role generator so you could use it like:

def role(role, options = {})
  FactoryGirl.create :role, options.merge(:name => role)
end

account = FactoryGirl.create :account, :role => role("student")
like image 155
Chris Heald Avatar answered Oct 06 '22 01:10

Chris Heald