Ruby on rails FactoryGirl:Populate a有许多保持关系的构建策略
我的问题似乎很常见,但我在文档或互联网本身中没有找到任何答案 这似乎是这个问题的复制品,但2,5年后,那个后工厂女孩改变了很多 我有一个模型,有很多关系,叫做照片。我想填充它,这与我选择的构建策略有很多关系 如果我调用Ruby on rails FactoryGirl:Populate a有许多保持关系的构建策略,ruby-on-rails,testing,factory-bot,Ruby On Rails,Testing,Factory Bot,我的问题似乎很常见,但我在文档或互联网本身中没有找到任何答案 这似乎是这个问题的复制品,但2,5年后,那个后工厂女孩改变了很多 我有一个模型,有很多关系,叫做照片。我想填充它,这与我选择的构建策略有很多关系 如果我调用offering=FactoryGirl.build\u stubbed:offering,:stay我希望offering.photos是stubbed模型的集合 我发现实现这一目标的唯一方法是: factory :offering do association :partn
offering=FactoryGirl.build\u stubbed:offering,:stay
我希望offering.photos
是stubbed模型的集合
我发现实现这一目标的唯一方法是:
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
没有必要说,它必须存在一个更好的方式来做到这一点
想法?您可以使用各种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
下面是Flipstone答案的一个稍微简洁的版本:
factory :offering do
trait :stay do
...
photos do
association :hotel_photo, :strategy => @build_strategy.class
end
end
end
这种事情对我来说很有用:
factory :offering do
trait :stay do
...
photos { |o| [o.association(:hotel_photo)] }
end
end
其他答案存在缺陷,反向关联未正确初始化,例如,
offering.photos.first.offering==offering
为false
。更糟糕的是,产品
对于每个照片
都是一个新的产品
此外,明确指定策略是多余的
要克服流程并简化事情:
factory :offering do
trait :stay do
...
photos do
association :hotel_photo, offering: @instance
end
end
end
@instance
是工厂目前正在创建的产品的一个实例。出于好奇,上下文是FactoryGirl::Evaluator
如果您不象我一样喜欢@实例
,您可以在evaluator.rb中查找以下内容:
def method_missing(method_name, *args, &block)
if @instance.respond_to?(method_name)
@instance.send(method_name, *args, &block)
我真的很喜欢本身的样子:
factory :offering do
trait :stay do
...
photos do
association :hotel_photo, offering: itself
end
end
end
一定要能够使用本身
,在计算器上取消定义它
:
FactoryGirl::Evaluator.class_eval { undef_method :itself }
它将被传递到@实例
,并将返回@实例
本身
为了提供包含多张照片的完整示例:
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(*)从酒店照片中点击数据库…
(在大多数情况下将返回0),请在断言中使用length
或size
事实上,这是一种更好的方式。我正在检查make(:hotel_photo)这样的方法是否存在,它尊重您的偏好,但这似乎很好。接受谢谢!我用send(hook,:thing)
删除了一点重复。如果这在任何工厂的通用助手中都可用,那就太好了。我已经创建了一个问题github来公开这个想法<代码>在(:stub)do | offering | offering.photos=[build_stubbed(:hotel_photo)]结束后
这不起作用。FactoryGirl引发错误:不允许存根模型访问database@Jared嗯,你用的是哪个版本的工厂女孩?另外,您是否有可能提供一个指向要点的链接,并复制该例外?在我看来,这适用于不太多的关联?我认为您不需要在这里指定策略。反向不适用于我,例如offering.photos.first.offering==offering
是false
。