Как создать имеет и принадлежит к многим ассоциациям в Factory girl
учитывая следующее
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
возможно, неудивительно, что это приводит к бесконечному циклу, поскольку фабрики рекурсивно используют друг друга для определения себя.
более удивительно, что я не нашел упоминания о том, как это сделать в любом месте, есть ли шаблон для определения необходимого фабрики или я делаю что-то принципиально неправильное?
11 ответов:
вот решение, которое работает для меня.
FactoryGirl.define do factory :company do #company attributes end factory :user do companies {[FactoryGirl.create(:company)]} #user attributes end end
Если вам понадобится конкретная компания, вы можете использовать завод таким образом
company = FactoryGirl.create(:company, #{company attributes}) user = FactoryGirl.create(:user, :companies => [company])
надеюсь, это будет полезно для кого-то.
Factorygirl с тех пор был обновлен и теперь включает обратные вызовы для решения этой проблемы. Взгляните на http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl для получения дополнительной информации.
на мой взгляд, просто создайте две разные фабрики, такие как:
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
то, что работало для меня было установление связи при использовании фабрики. Используя Ваш пример:
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
предупреждение: изменить пользователей: [пользователь] на :Пользователи => [пользователь] для ruby 1.8.x
нашел этот способ хороший и verbose:
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 так, как вы это сделали.
вы можете определить новую фабрику и использовать 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