Problem with Factory_girl, association and after_initialize

前端 未结 3 1610
予麋鹿
予麋鹿 2021-02-07 02:12

I have a Family class so defined:

class Family < ActiveRecord::Base
  after_initialize :initialize_family
  belongs_to :user
  validates :user, 
       :prese         


        
相关标签:
3条回答
  • 2021-02-07 02:20

    This is the answer I got from Joe Ferris:

    factory_girl doesn't pass arguments to the constructor. It uses #user= on your model, and instantiates it without any arguments.

    and this one from Ben Hughes:

    To elaborate on what Joe is saying, after_initialize methods are called immediately upon object initialization, and that time indeed user has not been set.

    So for example while this will work:

    family = Family.create!(:user => @user) # or @user.families.create ...
    

    This will not (which is what factory_girl is doing under the hood):

    family = Family.new
    family.user = @user
    family.save!
    

    Just in general you want to be real careful using after_initialize, as remember this is called on every object initialization. A Family.all call on 1,000 objects will cause that to get called 1,000 times.

    Sounds like in this instance you might be better of using a before_validation instead of after_initialize.

    The following syntax also works for testing in rspec:

    let (:family) { Family.create(:user => @user) }
    
    0 讨论(0)
  • 2021-02-07 02:30

    I believe that it's because the association is lazy, thus in the "after_initialize" there's no user yet.

    http://rdoc.info/github/thoughtbot/factory_girl/v1.3.3/file/README.rdoc

    Perhaps you can directly call one factory from another, but I didn't try this, e.g.

    f.user Factory(:user)
    
    0 讨论(0)
  • 2021-02-07 02:34

    Since after_initialize is triggered after new objects are instantiated and factory_girl builds instances by calling new without any arguments by default, you must use initialize_with to overwrite the default build.

    FactoryGirl.define do
      factory :family do
        initialize_with { new(user: build(:user)) }
      end
    end
    
    0 讨论(0)
提交回复
热议问题