hakunin
hakunin

Reputation: 4231

How to simplify complex creations with FactoryGirl

In my app, I have this kind of structure:

Organization
  -- members (through many to many table)
  -- projects
    -- boards
      -- cards
        -- owner (user that must be a member of organization)

A lot of testing happens around cards, so I end up with too hairy setup methods, since card has to have organization, project, board and its owner.

How would you go about implementing a decent factory for card in this case?

Current solution I'd like to clean up:

Note I am missing the board connection to project, a board has columns and ideally the card should be dropped onto one of the columns.

FactoryGirl.define do
  factory :card do
    _project = FactoryGirl.create(:project)
    project _project
    subject { Faker::Hacker.say_something_smart }
    author _project.organization.members.first
  end

  factory :user do
    first_name { Faker::Name.first_name }
    last_name { Faker::Name.last_name }
    email { Faker::Internet.email }
    password 'mypassword'
    password_confirmation 'mypassword'
  end

  factory :project do
    name Faker::Internet.domain_name
    organization
  end

  factory :organization do
    name Faker::Company.name

    after(:create) do |post|
      2.times {
        post.members << FactoryGirl.create(:user)
      }
    end
  end

end

Upvotes: 0

Views: 25

Answers (1)

Thach Chau
Thach Chau

Reputation: 111

You can try this structure

FactoryGirl.define do
 factory :project
 end
end

FactoryGirl.define do
 factory :organization do
 end
end

FactoryGirl.define do
  factory :board
   project
  end
 end

FactoryGirl.define do
 factory :owner do
  organization
 end
end

FactoryGirl.define do
 factory :card do
  board
  owner
  transient do
   owner_organization false
  end

  after(:create) do |card, evaluator|
   card.owner.update_attributes(organization: evaluator.organization) if evaluator.organization
  end
 end
end

Then you can try the follow approachs

  • Default values of Project, Board and Owner FacctoryGirl.create(:card)
  • Customized values with transient attributes FactoryGirl.create(:card, owner_organization: Organization.last)
  • Customized values FactoryGirl.create(:card, board: FactoryGirl.create(:board, project: FactoryGirl.create(:project)))y

Upvotes: 1

Related Questions