Matt Elhotiby
Matt Elhotiby

Reputation: 44066

How do I save a local variable within a factory

I have this example

FactoryGirl.define do
  @site = FactoryGirl.create(:my_site)
  factory :user do
    email               { Faker::Internet.email }
    first_name          { Faker::Name.first_name }
    last_name           { Faker::Name.last_name }
    password            { 'TarXlrOPfaokNOzls2U8' }
    active_directory    { '0' }
    companies           { [FactoryGirl.create(:company, site: @site)] }
    sites               { [@site] }
  end
end

Is there a way to achieve this with a let or something...

FactoryGirl.define do
  factory :user do
    email               { Faker::Internet.email }
    first_name          { Faker::Name.first_name }
    last_name           { Faker::Name.last_name }
    password            { 'TarXlrOPfaokNOzls2U8' }
    active_directory    { '0' }
    companies           { [FactoryGirl.create(:company, site: FactoryGirl.create(:my_site))] }
    sites               { [FactoryGirl.create(:my_site)] }

  end
end

This works but it creates two my_site which is a Site object but I need them to be the same...any idea on how to achieve this

Upvotes: 15

Views: 8506

Answers (3)

MegaTux
MegaTux

Reputation: 1651

An easy way is defining a transient attribute. It has the extra benefit of be overridable on factory instantiation.

  transient do
    site { FactoryGirl.create(:my_site) { true } }
  end

Upvotes: 0

RSmithlal
RSmithlal

Reputation: 384

I finally figured out a good way to do this. This question is pretty old, but I thought I'd post an answer in case other people come across this.

You can use a before(:create) callback (or before(:build) if thats your use case) to set the sites collection, and then assign the first element of the sites collection to the newly created company in the company collection.

More information about FactoryBot callbacks can be found here.

Just so readers know, I'm using the new FactoryBot class name as FactoryGirl is deprecated.

FactoryBot.define do
  factory :user do
    email               { Faker::Internet.email }
    first_name          { Faker::Name.first_name }
    last_name           { Faker::Name.last_name }
    password            { 'TarXlrOPfaokNOzls2U8' }
    active_directory    { '0' }

    before(:create) do |user|
      user.sites << FactoryBot.create(:my_site)
      user.companies << FactoryBot.create(:company, site: user.sites.first)
    end
  end
end

Upvotes: 6

tokland
tokland

Reputation: 67870

Probably the simplest is to use a local variable:

FactoryGirl.define do
  site = FactoryGirl.create(:my_site)

  factory :user do
    email               { Faker::Internet.email }
    first_name          { Faker::Name.first_name }
    last_name           { Faker::Name.last_name }
    password            { 'TarXlrOPfaokNOzls2U8' }
    active_directory    { '0' }
    companies           { [FactoryGirl.create(:company, site: site)] }
    sites               { [site] }
  end
end

Upvotes: 25

Related Questions