How to create has_and_belongs_to_many associations in Factory girl

前端 未结 11 606
生来不讨喜
生来不讨喜 2020-12-07 09:27

Given the following

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_m         


        
相关标签:
11条回答
  • 2020-12-07 09:50

    What worked for me was setting the association when using the factory. Using your example:

    user = Factory(:user)
    company = Factory(:company)
    
    company.users << user 
    company.save! 
    
    0 讨论(0)
  • 2020-12-07 09:53

    You can define new factory and use after(:create) callback to create a list of associations. Let's see how to do it in this example:

    FactoryBot.define do
    
      # user factory without associated companies
      factory :user do
        # user attributes
    
        factory :user_with_companies do
          transient do
            companies_count 10
          end
    
          after(:create) do |user, evaluator|
            create_list(:companies, evaluator.companies_count, user: user)
          end
        end
      end
    end
    

    Attribute companies_count is a transient and available in attributes of the factory and in the callback via the evaluator. Now, you can create a user with companies with the option to specify how many companies you want:

    create(:user_with_companies).companies.length # 10
    create(:user_with_companies, companies_count: 15).companies.length # 15
    
    0 讨论(0)
  • 2020-12-07 09:54

    Found this way nice and verbose:

    FactoryGirl.define do
      factory :foo do
        name "Foo" 
      end
    
      factory :bar do
        name "Bar"
        foos { |a| [a.association(:foo)] }
      end
    end
    
    0 讨论(0)
  • 2020-12-07 09:55

    Update for Rails 5:

    Instead of using has_and_belongs_to_many association, you should consider: has_many :through association.

    The user factory for this association looks like this:

    FactoryBot.define do
      factory :user do
        # user attributes
    
        factory :user_with_companies do
          transient do
            companies_count 10 # default number
          end
    
          after(:create) do |user, evaluator|
             create_list(:companies, evaluator.companies_count, user: user)
          end
        end
      end
    end
    

    You can create the company factory in a similar way.

    Once both factories are set, you can create user_with_companies factory with companies_count option. Here you can specify how many companies the user belongs to: create(:user_with_companies, companies_count: 15)

    You can find detailed explanation about factory girl associations here.

    0 讨论(0)
  • 2020-12-07 09:56

    First of all I strongly encourage you to use has_many :through instead of habtm (more about this here), so you'll end up with something like:

    Employment belongs_to :users
    Employment belongs_to :companies
    
    User has_many :employments
    User has_many :companies, :through => :employments 
    
    Company has_many :employments
    Company has_many :users, :through => :employments
    

    After this you'll have has_many association on both sides and can assign to them in factory_girl in the way you did it.

    0 讨论(0)
提交回复
热议问题