counter_cache不会减少ActiveReord中的has_many关联

时间:2010-10-11 01:27:18

标签: ruby-on-rails activerecord counter-cache

我的Rails 3应用程序有2个模型,第三个是它们和has_many关系之间的连接表。基本上,User和Show由SavedShow加入,允许用户保存节目列表:

class Show < ActiveRecord::Base
  has_many :saved_shows
  has_many :users, :through => :saved_shows
end

class User < ActiveRecord::Base
  has_many :saved_shows
  has_many :shows, :through => :saved_shows
end

class SavedShow < ActiveRecord::Base
  belongs_to :user, :counter_cache => :saved_shows_count
  belongs_to :show
end

我注意到counter_cache字段(shows_saved_count)会自动递增,但不会递减。该问题的核心似乎是从用户列表中删除节目是通过删除完成的,这不会触发counter_cache的更新:

current_user.shows.delete(@show)

但是,我不能在这里调用destroy方法,因为它不仅删除了SavedShow中的User / Show关联,还删除了Show对象本身,这不是我想要的。

这种场景中的counter_cache不适合使用吗?

在2009年,似乎有一个discussion作为一个错误,并讨论了修复,但我仍然在最新的Rails 3.0中看到了这个问题。

我只是在模型中编写自己的自定义处理,但似乎没有我可以挂钩的after_delete回调(可能这就是减少首先不起作用的原因)。现在,在我自己的代码中只有一个地方可以删除关联,所以我只是手动调用更新计数器,但这似乎是一个基本的缺点或ActiceRecord与counter_cache的关联的错误,我想知道我是不是只是错过了什么。

如果这确实是counter_caches的真正问题,那么最好的解决方法是什么?

2 个答案:

答案 0 :(得分:1)

相同的问题,但在Rails 2.3上。 值得注意的是还添加了一个触摸,如:

belongs_to :user, :counter_cache => :saved_shows_count, :touch => true

不会更新counter.delete(object)上的计数器缓存或相关的updated_at字段。

要解决这个问题通常我们会操纵连接模型,但这也有一些缺点。

补丁在这里:https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2824-patch-has_many-through-doesnt-update-counter_cache-on-join-model-correctly#ticket-2824-18

答案 1 :(得分:0)

在Rails 5中解决了一个相关问题(通过连接表具有自引用计数器缓存),并按如下所示进行了修复:

class User < ActiveRecord::Base
  has_many :saved_shows, :counter_cache => :saved_shows_count
  has_many :shows, :through => :saved_shows
end

https://guides.rubyonrails.org/association_basics.html#options-for-has-many-counter-cache