Populating an association with children in factory_girl

前端 未结 5 1959
没有蜡笔的小新
没有蜡笔的小新 2020-12-12 17:16

I have a model Foo that has_many \'Bar\'. I have a factory_girl factory for each of these objects. The factory for Bar has an association to Foo; it will instan

相关标签:
5条回答
  • 2020-12-12 17:43

    FactoryGirl now has a :method => :build option you can use on the association, which will build the associated object rather than creating it.

    #64: Building an object creates associations

    0 讨论(0)
  • 2020-12-12 17:43

    Using factory_girl-4.5.0, create n child objects in a parent object factory

    FactoryGirl.define do
      factory :foo do
        name "test"        
    
        after(:build) do |instance|
          n.times { instance.bars << FactoryGirl.create(:bar) }          
        end
      end
    end
    
    0 讨论(0)
  • 2020-12-12 17:57

    FactoryGirl 4.3.0 is calling save! on an association when calling build on the parent object, which i believe is not intended to be the correct behavior.

    After digging through the FactoryGirl code, adding strategy: :build to the association definition in the factory seems now be creating my association without calling save!.

    0 讨论(0)
  • 2020-12-12 17:58

    You can use the association method both ways:

    Factory.define :foo do |f|
      # ...
      f.association :bar
    end
    

    If that won't work, you can associate them manually using a callback. Here's an example from one of my apps:

    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
    
    0 讨论(0)
  • 2020-12-12 18:01

    The Factory.after_ hooks appear to be the only way to do this successfully. I've figured out a way to maintain the build strategy without duplicating code:

    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
    

    The documentation states that after_build will be called before after_create if the :create build strategy is used. If :build is used, then only after_build is called, and everyone is happy.

    I've also created an abstracted generally-applicable version at this gist to keep things DRY.

    0 讨论(0)
提交回复
热议问题