Comment créer des associations de has_and_belongs_to_many dans Factory Girl
-
18-09-2019 - |
Question
Dans le cas suivant
class User < ActiveRecord::Base
has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :users
end
comment définissez-vous les usines pour les entreprises et les utilisateurs, y compris l'association bidirectionnelle? Voici ma tentative
Factory.define :company do |f|
f.users{ |users| [users.association :company]}
end
Factory.define :user do |f|
f.companies{ |companies| [companies.association :user]}
end
J'essaie
Factory :user
Peut-être sans surprise, cela se traduit par une boucle infinie comme les usines utilisent de manière récursive à l'autre pour définir elles-mêmes.
De façon plus surprenante, je ne l'ai pas trouvé une mention de la façon de le faire partout, est-il un modèle pour définir les usines nécessaires ou que je fais quelque chose de fondamentalement mauvais?
La solution 2
factorygirl a depuis été mis à jour et comprend maintenant callbacks pour résoudre ce problème. Jetez un oeil à http://robots.thoughtbot.com/post / 254496652 / aint-no-calla-back-fille pour plus d'informations.
Autres conseils
Voici la solution qui fonctionne pour moi.
FactoryGirl.define do
factory :company do
#company attributes
end
factory :user do
companies {[FactoryGirl.create(:company)]}
#user attributes
end
end
si vous avez besoin entreprise spécifique, vous pouvez utiliser l'usine de cette façon
company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])
Je espère que cela sera utile pour quelqu'un.
À mon avis, Il suffit de créer deux usines différentes comme:
Factory.define :user, :class => User do |u| # Just normal attributes initialization end Factory.define :company, :class => Company do |u| # Just normal attributes initialization end
Lorsque vous écrivez les cas-tests pour l'utilisateur alors il suffit d'écrire comme ceci
Factory(:user, :companies => [Factory(:company)])
Espérons que cela fonctionnera.
Je ne pouvais pas trouver un exemple pour le cas ci-dessus mentionné sur le site fourni. (Seulement 1: N et assocations polymorphes, mais pas HABTM). J'ai eu un cas similaire et mon code ressemble à ceci:
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
Ce qui a fonctionné pour moi installais l'association lors de l'utilisation de l'usine. En utilisant votre exemple:
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
Attention: Changement d'utilisateur: [utilisateur] à: utilisateurs => [utilisateur] pour 1.8.x rubis
trouvé cette façon agréable et bavard:
FactoryGirl.define do
factory :foo do
name "Foo"
end
factory :bar do
name "Bar"
foos { |a| [a.association(:foo)] }
end
end
Tout d'abord, je vous encourage fortement à utiliser has_many: par lieu de HABTM (plus à ce sujet ici ), de sorte que vous finirez avec quelque chose comme:
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
Après cela, vous aurez l'association has_many des deux côtés et peut les affecter à l'factory_girl de la manière que vous l'avez fait.
Mise à jour pour Rails 5:
Au lieu d'utiliser l'association has_and_belongs_to_many
, vous devriez envisager:. Association has_many :through
L'usine utilisateur de cette association ressemble à ceci:
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
Vous pouvez créer l'usine de l'entreprise d'une manière similaire.
Une fois que les deux usines sont réglées, vous pouvez créer l'usine de user_with_companies
avec companies_count option
. Ici, vous pouvez spécifier le nombre de sociétés auquel l'utilisateur appartient: create(:user_with_companies, companies_count: 15)
Pour HABTM je traits et callbacks .
Disons que vous avez les modèles suivants:
class Catalog < ApplicationRecord
has_and_belongs_to_many :courses
…
end
class Course < ApplicationRecord
…
end
Vous pouvez définir l'usine ci-dessus :
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