t0rpedo
t0rpedo

Reputation: 60

factory_girl (4.2.0) many-to-many relationship

I want to properly establish a many-to-many factory set using FactoryGirl 4.2.0. I keep running into documentation/examples with outdated syntax from previous FactoryGirl versions mixed together and it just isn't working for me.

How do I set up this scenario given the following two resources and their linking table:

class User < ActiveRecord::Base
  has_many :user_registrations
  has_many :registrations, through: :user_registrations
end

class UserRegistration < ActiveRecord::Base
  belongs_to :user
  belongs_to :registration
end

class Registration < ActiveRecord::Base
  has_many :user_registrations
  has_many :users, through: :user_registrations
end

This is what I have so far, as per the documentation found here. This is as close as I've come so far into any real progress.

FactoryGirl.define do

  factory :registration do
    user
  end

  factory :user, class: User do
    sequence(:email) { |n| "foo#{n}@example.com" }
    password "password"

    factory :user_with_registrations do

      ignore do
        registrations_count 1
      end

      after(:create) do |user, evaluator|
        registrations FactoryGirl.create_list(:registration, evaluator.registrations_count, user: user)
      end
    end
  end
end

Which fails in the following manner, which I realize is because this setup is stated to be for a one-to-many relationship.

1) User Login Success
     Failure/Error: user = FactoryGirl.create(:user_with_registrations)
     NoMethodError:
       undefined method `user=' for #<Registration:0x007fc48e2ca768>
     # ./spec/factories.rb:18:in `block (4 levels) in <top (required)>'

What is the correct way to define a factory set for the many-to-many scenario using the latest FactoryGirl syntax? (4.2.0)

Thanks!

Upvotes: 3

Views: 2458

Answers (2)

Kristiina
Kristiina

Reputation: 533

For me it lookes like you have to make the has_many associations for Registrations and Users through UserRegistrations. This would then look like

    factory :user_registration do
       association :user
       association :registration
    end

    factory :user do
       ..setup for email and password

       factory :user_with_registrations do

          ignore do
            registrations_count 1
          end

          after(:create) do |user, evaluator|
            FactoryGirl.create_list(:user_registration, evaluator.registrations_count, user: user)
          end
       end
    end

    factory :registration do
       ..setup for registration

       factory :registration_with_user do

          ignore do
            users_count 1
          end

          after(:create) do |registration, evaluator|
            FactoryGirl.create_list(:user_registration, evaluator.users_count, registration: registration)
          end
       end
    end

Upvotes: 6

Benjamin Bouchet
Benjamin Bouchet

Reputation: 13181

I think I ran through this before, and the problem (less than obvious you'll agree on that) it that you use a constant name in your factory definitions.

Try to use a string instead, like this:

factory :user, class: 'User' do
  ...

Upvotes: 0

Related Questions