3

我的 Rails 3 应用程序有 2 个模型,第三个模型是它们之间的连接表及其 has_many 关系。基本上,用户和节目由 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 年,似乎就有关于这个问题的讨论,并讨论了修复,但我仍然在最新的 Rails 3.0 中看到了这个问题。

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

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

4

2 回答 2

1

这里有同样的问题,但在 Rails 2.3 上。值得注意的是,它还添加了一点触感,例如:

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

不会更新计数器缓存,也不会更新 association.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

于 2010-11-17T19:48:22.950 回答
1

在 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

[导轨 6]

在标准 has_many through 关系上:

class Parent < ApplicationRecord

has_many :joins,
         foreign_key: :parent_id,
         dependent: :destroy,
         counter_cache: :joins_count

has_many :children, through: :joins, source: 'child'
...


class Join < ApplicationRecord
  belongs_to :parent, counter_cache: :joins_count
  belongs_to :child
end

计数器缓存必须在两边都指定,否则我们不会在删除关系时递减

于 2019-01-07T09:42:09.423 回答