2011-08-26 27 views
4

創造記錄時,這是我的User模型及其Subscription的Rails協會回調不運行以另一種方式

# app/models/user.rb 
class User < ActiveRecord::Base 
    has_many :subscriptions, :before_add => :cancel_subscriptions! 

    def cancel_subscriptions!(new_subscription=nil) 
    subscriptions.each(&:cancel!) 
    end 
end 

# app/models/subscription.rb 
class Subscription < ActiveRecord::Base 
    belongs_to :user 
end 

所以,當我做some_user.subscriptions.create,它執行:cancel_subscriptions!回調,然後我很高興。但後來我做Subscription.create :user => some_user回調似乎並沒有被調用,我感到傷心,所以非常非常傷心。

有沒有一種方法可以確保在創建與User關聯的Subscription時執行回調?

PD:我真的很想不必寫在我的Subscription模型:before_create,因爲我覺得取消所有預訂應該是User模型的責任。

+0

如果用戶正在運行show(這是合理的),那麼'Subscription.create:user => some_user'是否有意義?代碼本身是有道理的,但也許不是從API的角度來看,如果用戶運行秀,那麼用戶應該運行整個演出。 –

+0

我完全同意,@mu!實際上,我每次都使用'some_user.subscriptions.create'。這更多是一種偏執/技術好奇的問題。 –

+2

我認爲':before_add'附加到集合上,但集合不夠聰明,無法知道背後發生的事情。 –

回答

2

從技術上講,:inverse_of選項belongs_to應該處理這種情況。具體而言,讓協會的另一方知道這方面的變化。但是這隻適用於另一面是has_one。從文檔不清楚,但你可以see it the source

因此截至目前還沒有辦法讓它自動工作。

有關PD的說明:您確實希望將訂閱功能從用戶模型中移除。管理用戶模型中的訂閱會增加耦合性。而且,正如您擁有Subscription模式一樣,無論如何都要做到這一點,併爲單個用戶管理訂閱。無論如何,before_add並不是管理訂閱的好地方。你正在執行一個hook_t中的破壞性動作,它在任何資源被保存之前運行。也就是說,您可以取消所有訂閱,並且新訂閱未通過驗證。因此,你已經失去了舊訂閱(你不知道哪一個是以前活躍的),並且你有一個無法保存的無效新訂閱。