Hoe has_and_belongs_to_many associaties te maken in Factory girl

Gezien het volgende

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

hoe definieer je fabrieken voor bedrijven en gebruikers, inclusief de bidirectionele associatie? Hier is mijn poging

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

nu probeer ik

Factory :user

Het is misschien niet verwonderlijk dat dit resulteert in een oneindige lus, aangezien de fabrieken elkaar recursief gebruiken om zichzelf te definiëren.

Verrassenderwijs heb ik nergens vermeld hoe ik dit moet doen, is er een patroon voor het definiëren van de noodzakelijke fabrieken of doe ik iets fundamenteel verkeerd?


Antwoord 1, autoriteit 100%

Hier is de oplossing die voor mij werkt.

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

als u een specifiek bedrijf nodig heeft, kunt u de fabriek op deze manier gebruiken

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

Ik hoop dat dit iemand kan helpen.


Antwoord 2, autoriteit 30%

Factorygirl is sindsdien bijgewerkt en bevat nu callbacks om dit probleem op te lossen. Kijk eens op http://robots.thoughtbot.com/post /254496652/aint-no-calla-back-girlvoor meer info.


Antwoord 3, autoriteit 16%

Naar mijn mening, maak gewoon twee verschillende fabrieken zoals:

Fabriek.define :gebruiker, :class => Gebruiker doet |u|
 # Gewoon normale attributen initialisatie
 einde
 Fabriek.define :bedrijf, :class => Bedrijf doen |u|
 # Gewoon normale attributen initialisatie
 einde

Als je de testcases voor de gebruiker schrijft, schrijf dan gewoon zo

Fabriek(:gebruiker, :bedrijven => [Fabriek(:bedrijf)])

Hoop dat het werkt.


Antwoord 4, autoriteit 7%

Ik kon geen voorbeeld vinden voor het bovengenoemde geval op de aangeboden website. (Alleen 1:N en polymorfe associaties, maar geen habtm). Ik had een soortgelijk geval en mijn code ziet er als volgt uit:

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

Antwoord 5, autoriteit 4%

Wat voor mij werkte, was het instellen van de associatie bij het gebruik van de fabriek.
Uw voorbeeld gebruiken:

user = Factory(:user)
company = Factory(:company)
company.users << user 
company.save! 

Antwoord 6, autoriteit 3%

Zo leuk en uitgebreid gevonden:

FactoryGirl.define do
  factory :foo do
    name "Foo" 
  end
  factory :bar do
    name "Bar"
    foos { |a| [a.association(:foo)] }
  end
end

Antwoord 7, autoriteit 2%

 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

Waarschuwing:wijzig gebruikers: [gebruiker] in :users => [gebruiker] voor ruby ​​1.8.x


Antwoord 8

Voor HABTM heb ik eigenschappen en callbacks gebruikt.

Stel dat je de volgende modellen hebt:

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

U kunt bepalen de Factory boven

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

Antwoord 9

Allereerst wil ik u ten zeerste aan gebruik has_many: door middel van in plaats van HABTM (meer over dit hier ), dus je zult eindigen met iets als:

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

Hierna kun has_many vereniging aan beide zijden zult hebben en kan in factory_girl toe te kennen in de manier waarop je het deed.


Antwoord 10

Update voor Rails 5:

In plaats van has_and_belongs_to_manyvereniging, u zou moeten overwegen: has_many :throughvereniging

De gebruiker fabriek voor deze vereniging ziet er als volgt uit:

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

U kan het bedrijf de fabriek te creëren op een vergelijkbare manier.

Zodra beide fabrieken zijn ingesteld, u kunt maken user_with_companiesfabriek met companies_count option. Hier kunt u opgeven hoe veel bedrijven de gebruiker behoort: create(:user_with_companies, companies_count: 15)

U kunt gedetailleerde uitleg over fabriek meisje verenigingen vinden hier .


Antwoord 11

U kunt nieuwe fabriek en het gebruik opgeven na (: te maken) callback om een ​​lijst van de verenigingen te creëren. Laten we eens kijken hoe dat te doen in dit voorbeeld:

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

Kenmerk companies_count is een tijdelijke en verkrijgbaar in attributen van de fabriek en in de callback via de beoordelaar. Nu kun je een gebruiker met bedrijven te maken met de mogelijkheid om aan te geven hoeveel bedrijven je wilt:

create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15

Other episodes