2011-08-26 41 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中的破坏性动作,它在任何资源被保存之前运行。也就是说,您可以取消所有订阅,并且新订阅未通过验证。因此,你已经失去了旧订阅(你不知道哪一个是以前活跃的),并且你有一个无法保存的无效新订阅。

相关问题