125 votes

Comment créer des associations has_and_belongs_to_many dans Factory girl ?

Compte tenu des éléments suivants

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

comment définir des 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

maintenant j'essaie

Factory :user

Il n'est peut-être pas surprenant que cela aboutisse à une boucle infinie, les usines s'utilisant récursivement les unes les autres pour se définir.

Plus surprenant encore, je n'ai trouvé aucune mention de la façon de faire cela nulle part. Existe-t-il un modèle pour définir les usines nécessaires ou bien je fais quelque chose de fondamentalement faux ?

135voto

Suborx Points 2222

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 d'une entreprise spécifique, vous pouvez utiliser l'usine de cette manière.

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

J'espère que cela sera utile à quelqu'un.

4 votes

Merci, la plus soignée de toutes les solutions.

0 votes

Merci. Cela a réglé mon problème après des heures de frustration.

0 votes

Cela ne fonctionne pour moi que lorsque toutes les usines sont en place. un fichier ce qui est tout à fait indésirable. Par conséquent, la solution mentionnée par @opsb ci-dessous semble être la meilleure.

40voto

opsb Points 6860

Factorygirl a depuis été mis à jour et inclut maintenant des callbacks pour résoudre ce problème. Jetez un coup d'œil à http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl pour plus d'informations.

38 votes

Le lien ne dit pas vraiment comment gérer has_and_belongs_to_many... Je ne vois pas comment faire...

3 votes

La syntaxe de la fonction de rappel a été modifiée comme suit : after(:create) au lieu de after_create en fille d'usine comme mentionné ici : stackoverflow.com/questions/15003968/

22voto

Ashish Points 3221

A 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 test-cases pour l'utilisateur, écrivez simplement comme ceci

 Factory(:user, :companies => \[Factory(:company)\])

J'espère que ça va marcher.

2 votes

Merci, c'est le seul exemple que j'ai pu faire fonctionner. Factory girl est un gros casse-tête pour habtm.

0 votes

Cela ne fonctionne plus avec les versions récentes de FactoryGirl (je pense à Rails 3).

9voto

auralbee Points 2433

Je n'ai pas trouvé d'exemple pour le cas mentionné ci-dessus sur le site web fourni. (Seulement 1:N et des assocations polymorphes, mais pas de 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

4 votes

Que se passe-t-il s'il y a validation d'un nombre d'utilisateurs non nul ?

5voto

Larry Kooper Points 31

Ce qui a fonctionné pour moi, c'est de définir l'association lors de l'utilisation de l'usine. En utilisant votre exemple :

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

company.users << user 
company.save!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X