Programing

Factory Girl에서 has_and_belongs_to_many 연관을 작성하는 방법

crosscheck 2020. 7. 17. 19:17
반응형

Factory Girl에서 has_and_belongs_to_many 연관을 작성하는 방법


다음을 감안할 때

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

양방향 연관을 포함하여 회사 및 사용자의 팩토리를 어떻게 정의합니까? 여기 내 시도가 있습니다

Factory.define :company do |f|
  f.users{ |users| [users.association :company]}
end

Factory.define :user do |f|
  f.companies{ |companies| [companies.association :user]}
end

이제 나는 시도

Factory :user

공장이 서로를 재귀 적으로 사용하여 자신을 정의함에 따라 예기치 않게 이것은 무한 루프를 초래할 수 있습니다.

더 놀랍게도 어디서나이 작업을 수행하는 방법에 대한 언급을 찾지 못했습니다. 필요한 공장을 정의하는 패턴이 있습니까? 아니면 근본적으로 잘못된 일을하고 있습니까?


여기에 맞는 해결책이 있습니다.

FactoryGirl.define do

  factory :company do
    #company attributes
  end

  factory :user do
   companies {[FactoryGirl.create(:company)]}
   #user attributes
  end

end

특정 회사가 필요할 경우 이런 식으로 공장을 사용할 수 있습니다

company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])

이것이 누군가에게 도움이되기를 바랍니다.


Factorygirl은 이후 업데이트되었으며 이제이 문제를 해결하기위한 콜백을 포함합니다. 자세한 내용 http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl 을 참조하십시오.


제 생각에는 다음과 같이 두 개의 다른 공장을 만드십시오.

 Factory.define : user, : class => 사용자 수행 | u |
  # 그냥 일반 속성 초기화
 종료

 Factory.define : company, : class => 회사는 | u |
  # 그냥 일반 속성 초기화
 종료

사용자의 테스트 사례를 작성할 때 다음과 같이 작성하십시오.

 Factory (: user, : companies => [공장 (: 회사)])

그것이 효과가 있기를 바랍니다.


제공된 웹 사이트에서 위에서 언급 한 사례에 대한 예를 찾을 수 없습니다. (1 : N 및 다형성 연관이지만 habtm은 없음). 비슷한 경우가 있었고 코드는 다음과 같습니다.

Factory.define :user do |user|
 user.name "Foo Bar"
 user.after_create { |u| Factory(:company, :users => [u]) }
end

Factory.define :company do |c|
 c.name "Acme"
end

나를 위해 일한 것은 공장을 사용할 때 연결을 설정하는 것이 었습니다. 귀하의 예를 사용하여 :

user = Factory(:user)
company = Factory(:company)

company.users << user 
company.save! 

  factory :company_with_users, parent: :company do

    ignore do
      users_count 20
    end

    after_create do |company, evaluator|
      FactoryGirl.create_list(:user, evaluator.users_count, users: [user])
    end

  end

Warning: Change users: [user] to :users => [user] for ruby 1.8.x


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

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.


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.


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

For HABTM I used traits and callbacks.

Say you have the following models:

class Catalog < ApplicationRecord
  has_and_belongs_to_many :courses
end
class Course < ApplicationRecord
end

You can define the Factory above:

FactoryBot.define do
  factory :catalog do
    description "Catalog description"

    trait :with_courses do
      after :create do |catalog|
        courses = FactoryBot.create_list :course, 2

        catalog.courses << courses
        catalog.save
      end
    end
  end
end

참고URL : https://stackoverflow.com/questions/1484374/how-to-create-has-and-belongs-to-many-associations-in-factory-girl

반응형