我的问题似乎很常见,但我还没有发现的文档或Internet本身的任何答复。
这似乎这个问题的一个副本,同时尊重建立战略factory_girl的has_many但2,5年该职位factory_girl后发生了很大变化。
我有一个的has_many关系的模型叫做照片。 我想填充这个有很多关系保持我的选择构建策略。
如果我叫offering = FactoryGirl.build_stubbed :offering, :stay
我希望offering.photos
是存根模型的集合。
我找到了实现这一目标的唯一途径是这个:
factory :offering do
association :partner, factory: :named_partner
association :destination, factory: :geolocated_destination
trait :stay do
title "Hotel Gran Vía"
description "Great hotel in a great zone with great views"
offering_type 'stay'
price 65
rooms 70
stars 4
event_spaces 3
photos do
case @build_strategy
when FactoryGirl::Strategy::Create then [FactoryGirl.create(:hotel_photo)]
when FactoryGirl::Strategy::Build then [FactoryGirl.build(:hotel_photo)]
when FactoryGirl::Strategy::Stub then [FactoryGirl.build_stubbed(:hotel_photo)]
end
end
end
end
没必要说,它必须存在一个更好的方式做到这一点。
想法?
这里的Flipstone的回答稍微清洁的版本:
factory :offering do
trait :stay do
...
photos do
association :hotel_photo, :strategy => @build_strategy.class
end
end
end
您可以使用各种FactoryGirl回调:
factory :offering do
association :partner, factory: :named_partner
association :destination, factory: :geolocated_destination
trait :stay do
title "Hotel Gran Vía"
description "Great hotel in a great zone with great views"
offering_type 'stay'
price 65
rooms 70
stars 4
event_spaces 3
after(:stub) do |offering|
offering.photos = [build_stubbed(:hotel_photo)]
end
after(:build) do |offering|
offering.photos = [build(:hotel_photo)]
end
after(:create) do |offering|
offering.photos = [create(:hotel_photo)]
end
end
end
您也可以直接调用FactoryRunner类,并把它传递给使用构造策略。
factory :offering do
trait :stay do
...
photos do
FactoryGirl::FactoryRunner.new(:hotel_photo, @build_strategy.class, []).run
end
end
end
其他答案有一个缺陷,逆协会没有被正确初始化,如offering.photos.first.offering == offering
是false
。 更糟的是不正确而,该offering
是一种新的Offering
每个的photos
。
此外,明确指定的策略是多余的。
为了克服流动性并简化事情:
factory :offering do
trait :stay do
...
photos do
association :hotel_photo, offering: @instance
end
end
end
@instance
是实例Offering
由工厂目前正在创建。 对于好奇的,上下文是FactoryGirl::Evaluator
。
如果你不喜欢@instance
像我这样做,你可能看在evaluator.rb
并找到以下内容:
def method_missing(method_name, *args, &block)
if @instance.respond_to?(method_name)
@instance.send(method_name, *args, &block)
我真的很喜欢怎样itself
的样子:
factory :offering do
trait :stay do
...
photos do
association :hotel_photo, offering: itself
end
end
end
别能够使用itself
,取消定义它的Evaluator
:
FactoryGirl::Evaluator.class_eval { undef_method :itself }
它会被传递到@instance
并将返回@instance
本身。
为了提供有几张照片一个完整的例子的目的:
factory :offering do
trait :stay do
...
photos do
3.times.map do
association :hotel_photo, offering: itself
end
end
end
end
用法:
offering = FactoryGirl.build_stubbed :offering, :stay
offering.photos.length # => 3
offering.photos.all? { |photo| photo.offering == offering } # => true
要小心,因为预期有些事情可能无法正常工作:
-
offering.photos.first.offering_id
将令人惊奇地是nil
; -
offering.photos.count
将达到数据库与SELECT COUNT(*) FROM hotel_photos ...
(并且在大多数情况下返回0),请使用length
或size
的断言。
这种事情对我的作品:
factory :offering do
trait :stay do
...
photos { |o| [o.association(:hotel_photo)] }
end
end