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?

Était-ce utile?

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)

Vous trouverez des explications détaillées sur le

Vous pouvez définir une nouvelle usine et l'utilisation après (: créer) le rappel pour créer une liste d'associations. Voyons voir comment le faire dans cet exemple:

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

est un attribut companies_count transitoire et disponible dans les attributs de l'usine et le rappel par l'évaluateur. Maintenant, vous pouvez créer un utilisateur avec des entreprises avec la possibilité de spécifier le nombre de sociétés que vous voulez:

create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 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
scroll top