2012-07-10 5 views
1

RoR과 함께 FactoryGirl 3.3.0을 사용 중입니다. 3.2.3FactoryGirl 콜백이 실행되지 않아야하는 이유는 무엇입니까?

프로필이 has_one 인 사용자 모델이 있습니다. 그래서 프로필이없는 사용자를 가질 수 있습니다 실행 build_profile : 내 RSpec에 테스트에서

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 

나는 때때로 before_create을 방지 할 필요가있다. FactoryGirl 콜백으로이 문제를 해결합니다.

after(:build) {|user| user.class.skip_callback(:create, :before, :build_profile)} 

내 사용자 공장은 다음과 같이 정의됩니다.

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 

내 기대는 :new_user_without_profile:activated_user_without_profile는 동안 :new_user_with_profile:activated_user_with_profile 공장 않을 것 :user_without_profile에서 after(:build) 콜백을 상속 할 것이라고했지만, 꽤 그런 식으로 작동하지 않습니다. 여기 내 문제를 설명하기 위해 콘솔에서 발췌 한 내용이 있습니다.

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 

그래서, 내가 만들 처음 예상대로 new_user_with_profile는 프로필이 생성되지만 (A 만든 후 : new_user_without_profile를) 두 번째로, 그것은 더 이상하지 않습니다! after (: build) 콜백은 다시 호출되지 않는 것처럼 보입니다. (뭔가 코드를 출력하면 터미널에 표시되지 않습니다.) 나는 여기서 무엇이 잘못 될지 전혀 모른다. 다른 사람 있습니까?

답변

2

이 더러운 솔루션입니다하지만 당신은 factory :user_with_profile의 콜백의 정의를 쓰기 위해 노력했다 :

after(:build) {|user| user.class.set_callback(:create, :before, :build_profile)} 

가 작동 하는가를?

+0

아니요. 시도하지 않았지만 제대로 작동했습니다. 고마워, 적어도 내 테스트가 작동합니다. 그것은 실제로 더러운 해결책입니다 - 나는 실제로 잘못되고있는 것이 무엇인지 이해하기를 원합니다. – brad

+2

여기서 일어나는 일은 정말 간단합니다. 당신의'user.class.skip_callback (: create, : before, : build_profile)'선언을 보시오. 콜백은 클래스의 인스턴스가 아니라 클래스에 설정되기 때문에, 처음에'FactoryGirl.create : new_user_without_profile'을 호출하면 콜백을 건너 뛰도록 설정됩니다. 나중에 'FactoryGirl.create : new_user_with_profile'을 호출하면 이전에 삭제했기 때문에 자연스럽게 콜백이 설정되지 않습니다. 내 제안은 다시 설정하는 것입니다. – Gerry

+0

미안하지만 저를 위해 작동하지 않습니다. –

관련 문제