user938363
user938363

Reputation: 10368

How to use call back in FactoryGirl 3.3 to create child object in has_many association?

This question probably has been asked many times. Here is our version. There are user and user_level model in our rails 3.1 app. A user has_many user_levels.

class User < ActiveRecord::Base
  has_many :user_levels
  accepts_nested_attributes_for :user_levels, :allow_destroy => true
  validates_presence_of :user_levels
end

class UserLevel < ActiveRecord::Base
  belongs_to :user 
  validates :position, :presence => true
end

Here is what we have in FactoryGirl 3.3:

FactoryGirl.define do

  factory :user_level do 
    position             "admin"
    user
  end

  factory :user do     
    name                  "Test User"
    login                 'testuser'
    password              "password1"

    factory :user_with_levels do
      #user_levels
      after(:create) do |user|
        FactoryGirl(:user_level, :user => user)
      end
    end
  end
end

u = FactoryGirl.build(:user_with_levels) or u = FactoryGirl.create(:user_with_levels) are used in our rspec. The after create callback did not work and there are errors saying Validation failed: User levels can't be blank. What's wrong with the callback above? Thanks so much.

Upvotes: 0

Views: 1263

Answers (2)

user938363
user938363

Reputation: 10368

Here is a solution that works. It is based on the following post by Tim Riley: http://icelab.com.au/articles/factorygirl-and-has-many-associations/

FactoryGirl.define do

  factory :user_level do 
    position             "admin"
    user
  end

  factory :user do     
    name                  "Test User"
    login                 'testuser'
    password              "password1"

    #user_levels
    after(:build) do |user|
      user.user_levels << FactoryGirl.build(:user_level, :user => user)
    end
  end
end

The problem (user level can't be blank) is because there is no user level when user is saved. User level needs to be built along with the user.

Upvotes: 4

HargrimmTheBleak
HargrimmTheBleak

Reputation: 2167

I think it's because validations on your nested models fire whenever create tries to save a user factory. Have you tried using an after(:build) callback instead?

Upvotes: 1

Related Questions