I am using FactoryGirl 3.3.0 with RoR 3.2.3
I have a user model which has_one profile like so;
class User < ActiveRecord::Base
has_secure_password
has_one :profile, dependent: :destroy
accepts_nested_attributes_for :profile, update_only: true
attr_accessible :email, :username, :password, :password_confirmation, :profile_attributes
before_create :build_profile
end
class Profile < ActiveRecord::Base
attr_accessible :first_name, :last_name
belongs_to :user
validates :user, presence: true
validates :first_name, presence: true, on: :update
validates :last_name, presence: true, on: :update
end
In my rspec tests I need to sometimes prevent the before_create :build_profile from running so I can have a user without a profile. I manage this with a FactoryGirl callback
after(:build) {|user| user.class.skip_callback(:create, :before, :build_profile)}
My user factories are defined as follows;
FactoryGirl.define do
factory :user do
sequence(:email) {|n| "user_#{n}@example.com"}
sequence(:username) {|n| "user_#{n}"}
password "secret"
factory :user_with_profile do
factory :new_user_with_profile do
before(:create) {|user| user.activated = false}
end
factory :activated_user_with_profile do
before(:create) {|user| user.activated = true}
end
end
factory :user_without_profile do
after(:build) {|user| user.class.skip_callback(:create, :before, :build_profile)}
factory :new_user_without_profile do
before(:create) {|user| user.activated = false}
end
factory :activated_user_without_profile do
before(:create) {|user| user.activated = true}
end
end
end
end
My expectation was that the :new_user_without_profile and :activated_user_without_profile would inherit the after(:build) callback from :user_without_profile while the :new_user_with_profile and :activated_user_with_profile factories would not, but it’s not quite working like that. Here’s an excerpt from the console to demonstrate my problem;
irb(main):001:0> user = FactoryGirl.create :new_user_with_profile
irb(main):002:0> user.profile
=> #<Profile id: 11, first_name: "", last_name: "", created_at: "2012-07-10 08:40:10", updated_at: "2012-07-10 08:40:10", user_id: 18>
irb(main):003:0> user = FactoryGirl.create :new_user_without_profile
irb(main):004:0> user.profile
=> nil
irb(main):005:0> user = FactoryGirl.create :new_user_with_profile
irb(main):006:0> user.profile
=> nil
So, the first time I create a :new_user_with_profile, a profile is created as expected but the second time (after creating a :new_user_without_profile), it doesn’t any more! The after(:build) callback doesn’t seem to be getting called again (if I add some code to it to output something, I don’t see it in the terminal). I have no idea what’s going wrong here. Does anyone else?
This is a dirty solution but have you tried to write the definition of the callback in the
factory :user_with_profile:Does it work?