Como criar associações has_and_belongs_to_many em Factory Girl
-
18-09-2019 - |
Pergunta
Dado o seguinte
class User < ActiveRecord::Base
has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :users
end
Como você define fábricas para empresas e usuários, incluindo a associação bidirecional? Aqui está a minha tentativa
Factory.define :company do |f|
f.users{ |users| [users.association :company]}
end
Factory.define :user do |f|
f.companies{ |companies| [companies.association :user]}
end
Agora eu tento
Factory :user
talvez sem surpresa Isto resulta num ciclo infinito como as fábricas utilizam recursivamente uns aos outros para definir-se.
O mais surpreendente que eu não encontrei uma menção de como fazer isso em qualquer lugar, há um padrão para definir as fábricas necessárias ou estou fazendo algo fundamentalmente errado?
Solução 2
Factorygirl já foi atualizado e agora inclui retornos de chamada para resolver este problema. Dê uma olhada na http://robots.thoughtbot.com/post / 254496652 / aint-no-calla-back-girl para mais informações.
Outras dicas
Aqui está a solução que funciona para mim.
FactoryGirl.define do
factory :company do
#company attributes
end
factory :user do
companies {[FactoryGirl.create(:company)]}
#user attributes
end
end
se você vai precisar empresa específica que você pode usar fábrica desta forma
company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])
Espero que isso será útil para alguém.
Na minha opinião, basta criar duas fábricas diferentes, como:
Factory.define :user, :class => User do |u| # Just normal attributes initialization end Factory.define :company, :class => Company do |u| # Just normal attributes initialization end
Quando você escreve os estudos de casos para o usuário, em seguida, basta escrever como este
Factory(:user, :companies => [Factory(:company)])
A esperança que vai funcionar.
Eu não poderia encontrar um exemplo para o caso mencionado acima no site fornecido. (Apenas 1: N e assocations polimórficas, mas não habtm). Eu tive um caso semelhante e minha aparência código como este:
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
O que funcionou para mim foi a criação da associação ao usar a fábrica. Usando o seu exemplo:
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
Aviso: usuários Mudança: [usuário] para: users => [usuário] para Ruby 1.8.x
Encontrado desta forma agradável e detalhado:
FactoryGirl.define do
factory :foo do
name "Foo"
end
factory :bar do
name "Bar"
foos { |a| [a.association(:foo)] }
end
end
Primeiro de tudo eu encorajamos você a usar has_many: through em vez de habtm (mais sobre este aqui ), então você vai acabar com algo como:
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
Após isso, você vai ter associação has_many em ambos os lados e pode atribuir a eles em factory_girl da maneira que você fez isso.
Atualização para Rails 5:
Em vez de usar associação has_and_belongs_to_many
, você deve considerar:. Associação has_many :through
A fábrica de usuário para esta associação parece com isso:
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
Você pode criar a fábrica da empresa de uma forma similar.
Uma vez que ambas as fábricas estão definidas, você pode criar fábrica user_with_companies
com companies_count option
. Aqui você pode especificar quantas empresas o usuário pertence: create(:user_with_companies, companies_count: 15)
Você pode encontrar explicação detalhada sobre fábrica associações menina aqui .
Você pode definir nova fábrica e após uso (: criar) de retorno de chamada para criar uma lista de associações. Vamos ver como fazê-lo neste exemplo:
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
Atributo companies_count é um transiente e disponível em atributos da fábrica e no retorno de chamada via o avaliador. Agora, você pode criar um usuário com empresas com a opção para especificar quantas empresas você quer:
create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15
Para HABTM Eu costumava traços e retornos de chamada .
Digamos que você tenha os seguintes modelos:
class Catalog < ApplicationRecord
has_and_belongs_to_many :courses
…
end
class Course < ApplicationRecord
…
end
Você pode definir a fábrica acima :
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