2012-07-10 21 views
1

我使用的FactoryGirl 3.3.0 RoR 3.2.3爲什麼我的FactoryGirl回調不應該運行?

我有一個像這樣has_one配置文件的用戶模型;

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 

在我的RSpec的測試中,我需要有時防止before_create:build_profile運行,所以我可以有沒有個人資料的用戶。我用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將從:user_without_profile繼承after(:build)回調而:new_user_with_profile:activated_user_with_profile工廠不會,但它不太那樣工作。以下是控制檯的一個摘錄,以證明我的問題;

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,創建一個配置文件作爲預期,但第二次(創建後:new_user_without_profile),它沒有任何更多! after(:build)回調似乎沒有再次被調用(如果我添加了一些代碼來輸出內容,我沒有在終端中看到它)。我不知道這裏有什麼問題。還有其他人嗎?

回答

2

這是一個骯髒的解決方案,但你試過寫在factory :user_with_profile的回調的定義:

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

是否行得通?

+0

不,我沒有嘗試過,是的它確實有效。謝謝,至少讓我的測試工作。但它確實是一個骯髒的解決方案 - 我寧願瞭解這裏實際發生了什麼問題。 – brad 2012-07-10 18:09:18

+2

這裏發生的事情非常簡單。看到'user.class.skip_callback(:create,:before,:build_profile)'你的聲明?因爲回調是在類而不是在類的實例上設置的,所以當你第一次調用'FactoryGirl.create:new_user_without_profile'時,它設置爲跳過回調。稍後當你調用'FactoryGirl.create:new_user_with_profile'時,它自然沒有回調集,因爲你之前已經刪除了。我的建議是把它放回去,就是這樣。 – Gerry 2012-07-11 07:47:31

+0

抱歉,但它不適合我。 – 2015-12-02 05:57:12

相關問題