Как создать ассоциации has_and_belongs_to_many в Factory girl
-
18-09-2019 - |
Вопрос
Учитывая следующее
class User < ActiveRecord::Base
has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :users
end
как вы определяете фабрики для компаний и пользователей, включая двунаправленную ассоциацию?Вот моя попытка
Factory.define :company do |f|
f.users{ |users| [users.association :company]}
end
Factory.define :user do |f|
f.companies{ |companies| [companies.association :user]}
end
теперь я пытаюсь
Factory :user
Возможно, неудивительно, что это приводит к бесконечному циклу, поскольку фабрики рекурсивно используют друг друга для определения самих себя.
Что еще более удивительно, я нигде не нашел упоминания о том, как это сделать, есть ли шаблон для определения необходимых фабрик или я делаю что-то в корне неправильное?
Решение 2
Factorygirl с тех пор была обновлена и теперь включает обратные вызовы для решения этой проблемы.Взгляните на http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl для получения дополнительной информации.
Другие советы
Вот решение, которое работает для меня.
FactoryGirl.define do
factory :company do
#company attributes
end
factory :user do
companies {[FactoryGirl.create(:company)]}
#user attributes
end
end
если вам понадобится конкретная компания, вы можете использовать factory таким образом
company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])
Надеюсь, это кому-нибудь будет полезно.
На мой взгляд, просто создайте две разные фабрики, такие как:
Factory.define :user, :class => User do |u| # Just normal attributes initialization end Factory.define :company, :class => Company do |u| # Just normal attributes initialization end
Когда вы пишете тестовые примеры для пользователя, тогда просто напишите так
Factory(:user, :companies => [Factory(:company)])
Надеюсь, это сработает.
Я не смог найти пример для вышеупомянутого случая на предоставленном веб-сайте.(Только 1: N и полиморфные ассоциации, но без habtm).У меня был похожий случай, и мой код выглядит примерно так:
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
Что сработало для меня, так это установка ассоциации при использовании factory.Используя ваш пример:
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
Предупреждение: Менять пользователей:[пользователю] кому:users => [пользователь] для ruby 1.8.x
Нашел этот способ приятным и подробным:
FactoryGirl.define do
factory :foo do
name "Foo"
end
factory :bar do
name "Bar"
foos { |a| [a.association(:foo)] }
end
end
Прежде всего, я настоятельно рекомендую вам использовать has_many :through вместо habtm (подробнее об этом здесь), так что в итоге вы получите что-то вроде:
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
После этого у вас будет ассоциация has_many с обеих сторон, и вы сможете назначить их в factory_girl так, как вы это сделали.
Обновление для Rails 5:
Вместо того, чтобы использовать has_and_belongs_to_many
ассоциации, вам следует рассмотреть: has_many :through
ассоциация.
Фабрика пользователей для этой ассоциации выглядит следующим образом:
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
Вы можете создать фабрику компаний аналогичным образом.
Как только обе фабрики установлены, вы можете создать user_with_companies
фабрика с companies_count option
.Здесь вы можете указать, ко скольким компаниям принадлежит пользователь: create(:user_with_companies, companies_count: 15)
Вы можете найти подробное объяснение о ассоциации фабричных девушек здесь.
Вы можете определить новую фабрику и использовать обратный вызов after(:create) для создания списка ассоциаций.Давайте посмотрим, как это сделать в этом примере:
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
Атрибут companies_count является временным и доступен в атрибутах фабрики и в обратном вызове через оценщик.Теперь вы можете создать пользователя с компаниями с возможностью указать, сколько компаний вы хотите:
create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15
Для HABTM я использовал черты и обратные вызовы.
Допустим, у вас есть следующие модели:
class Catalog < ApplicationRecord
has_and_belongs_to_many :courses
…
end
class Course < ApplicationRecord
…
end
Ты можешь определите Фабрику выше:
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