23

如果您有 2 个模型,视频和类别,并且它们彼此之间具有“has_and_belongs_to_many”关系,那么当其中一个发生更改时,您如何执行触摸以使缓存无效?

您不能像使用一对多关系那样对它们进行“触摸”。现在,当我更改类别名称时,属于该类别的视频不知道更改,直到我使缓存无效。我的视图模板显示每个视频的类别名称。

4

2 回答 2

44

在要更新的模型上,您可以执行以下操作:

class Video < ActiveRecord::Base
  has_and_belongs_to_many :categories,
                          after_add: :touch_updated_at,
                          after_remove: :touch_updated_at

  def touch_updated_at(category)
    self.touch if persisted?
  end

end

现在,无论何时在视频中添加或删除类别,视频的 updated_at 时间戳都会更新。如果您希望在添加视频或从中删除视频时更新类别,您可以在类别类上执行相同的操作。

于 2014-05-28T23:10:47.150 回答
13

触摸只能在两种情况下使用。

记录在案

category = Category.first
category.touch

在belongs_to 关系上

belongs_to :category, :touch => true

因此,如果您想在 HABTM 关系上使用它,恐怕您必须手动完成。它可能是这样的:

class Category
  before_save :touch_videos

  def touch_videos
    videos.touch
  end
end

class Video
  def self.touch
    update_attributes(:updated_at => Time.now)
    # or
    each { |video| video.touch } # Make a proper touch
  end
end

请注意,如果您也希望允许视频触摸类别,则必须找到一种方法来避免“循环”更新。

每个&find_each

如果您更喜欢每个而不是 update_attributes,请使用 find_each 批量加载记录。这将避免在内存中同时加载所有记录并可能导致应用程序崩溃。如果您没有 10k 条记录,您可能不会看到任何差异,但随着表的增长,如果您使用每条记录,它会变慢甚至中断。

find_each(batch_size: 2000) { |video| video.touch }
于 2013-05-31T11:45:02.720 回答