Наведение ассоциации с детьми в factory_girl
У меня есть модель Foo
, которая has_many 'Bar'. У меня есть factory_girl factory для каждого из этих объектов. factory for Bar имеет связь с Foo; он будет создавать экземпляр Foo, когда он создает панель.
Мне нужен factory, который создает Foo, содержащий панель. В идеале этот бар будет создан через: bar factory и будет уважать стратегию сборки (создание/сборку), используемую для создания Foo.
Я знаю, что могу просто позвонить: bar factory, а затем захватить ссылку Foo из новой панели. Я бы хотел этого избежать; в моем тестовом примере важным объектом является Foo; вызов бар factory кажется немного обходным. Кроме того, я вижу необходимость в Foo с несколькими барами.
Возможно ли это в factory_girl? Как вы определяете эту взаимосвязь в родительском?
Ответы
Ответ 1
Factory.after_ hooks
представляется единственным способом сделать это успешно. Я понял способ сохранить стратегию сборки без дублирования кода:
Factory.define :foo do |f|
f.name "A Foo"
f.after(:build) { |foo|
foo.bars << Factory.build(:bar, :foo => foo)
}
f.after(:create) { |foo|
foo.bars.each { |bar| bar.save! }
}
end
В документации указано, что after_build
будет вызываться до after_create
, если используется стратегия построения :create
. Если используется :build
, тогда вызывается только after_build
, и все довольны.
Я также создал абстрактную общепринятую версию в этом контексте, чтобы сохранить вещи DRY.
Ответ 2
Вы можете использовать метод association
в обоих направлениях:
Factory.define :foo do |f|
# ...
f.association :bar
end
Если это не сработает, вы можете связать их вручную, используя обратный вызов. Вот пример из одного из моих приложений:
Factory.define :live_raid do |raid|
end
Factory.define :live_raid_with_attendee, :parent => :live_raid do |raid|
raid.after_create { |r| Factory(:live_attendee, :live_raid => r) }
end
Ответ 3
В FactoryGirl теперь есть опция :method => :build
, которую вы можете использовать в ассоциации, которая будет создавать связанный объект, а не создавать его.
# 64: Создание объекта создает ассоциации
Ответ 4
FactoryGirl 4.3.0 вызывает save!
в ассоциации при вызове build
на родительском объекте, который, я считаю, не предназначен для правильного поведения.
После копания кода FactoryGirl добавление strategy: :build
в определение ассоциации в factory кажется теперь созданием моей ассоциации без вызова save!
.
Ответ 5
Используя factory_girl-4.5.0
, создайте n дочерних объектов в родительском объекте factory
FactoryGirl.define do
factory :foo do
name "test"
after(:build) do |instance|
n.times { instance.bars << FactoryGirl.create(:bar) }
end
end
end