Rails 4:has_many中的counter_cache:通过与dependent :: destroy

时间:2015-08-28 16:23:48

标签: ruby-on-rails ruby-on-rails-4 has-many-through counter-cache

虽然已经提出了类似的问题:

它们都没有真正解决我的问题。

我有三个模型,有一个has_many:通过关联:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

加入管理模型具有以下属性:

id
user_id
calendar_id
role

我想计算每个calendars有多少user以及每个users有多少calendar

我将使用counter_cache,如下所示:

class Administration < ActiveRecord::Base
  belongs_to :user, counter_cache: :count_of_calendars
  belongs_to :calendar, counter_cache: :count_of_users
end

(当然还有相应的迁移,可以将:count_of_calendars添加到users表,将:count_of_users添加到calendars表。)

然而,我偶然发现了this warning in Rails Guides

  

4.1.2.4:依赖

     

如果将:dependent选项设置为:

     
      
  • :destroy,当对象被销毁时,将在其关联对象上调用destroy。
  •   
  • :删除,当对象被销毁时,所有关联的对象将直接从数据库中删除而不调用它们   破坏方法。
  •   
     

您不应在belongs_to关联上指定此选项   与另一个类的has_many关联相关联。这样做可以   导致数据库中的孤立记录。

因此,计算每个calendars有多少user以及users每个calendar有多少是一个好习惯?

1 个答案:

答案 0 :(得分:2)

好吧,dependent: :destroy会破坏关联的记录,但它不会更新counter_cache,因此您可能在counter_cache中计算错误。相反,您可以实现一个将销毁关联记录的回调,并更新您的counter_cache

class Calendar < ActiveRecord::Base

  has_many :administrations
  has_many :users, through: :administrations


  before_destroy :delete_dependents

  private
  def delete_dependents
    user_ids = self.user_ids
    User.delete_all(:calendar_id => self.id)
    user_ids.each do |u_id|
      Calendar.reset_counters u_id, :users
    end
  end
end

同样,也为User模型实现了这个