FactoryGirl:填充有很多关系保存构建策略
我的问题似乎很常见,但我在文档或互联网本身没有找到任何答案。
它似乎是这个问题的一个克隆has_many同时尊重factory_girl中的构建策略,但是在post-factory_girl改变了很多之后的2。5年。
我有一个名为照片的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
没必要说IT必须存在更好的方法。
想法?
这是一个稍微清洁的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
是每张photos
的新Offering
。
此外,明确指定策略是多余的。
要克服流程并简化事情:
factory :offering do trait :stay do ... photos do association :hotel_photo, offering: @instance end end end
@instance
是工厂目前创建的Offering
实例。 对于好奇的,上下文是FactoryGirl::Evaluator
。
如果您不像我这样喜欢@instance
,您可以查看@instance
并找到以下内容:
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 ...
(并且在大多数情况下将返回0SELECT COUNT(*) FROM hotel_photos ...
命中数据库,请在断言中使用length
或size
。
这种事对我有用:
factory :offering do trait :stay do ... photos { |o| [o.association(:hotel_photo)] } end end
- Rails Paperclip:update与update_attributes
- 从设计中获取错误“用户不响应’设计’方法”运行“rails generate devise:install”时
- 如何将此Ruby String转换为数组?
- ActiveRecord :: Base的未定义方法`mass_assignment_sanitizer =’:Class(NoMethodError)
- 如何在rails控制器中处理ActiveRecord :: RecordNotFound?
- Rails HTTParty获取超时::错误
- Rails 3:如何从Controller发送Javascript代码?
- 如何支持向后兼容Rails 2.3.4中Accept头处理的更改
- Heroku上的twitter-bootstrap-rails:Glyphicons显示为正方形