如果您有 2 个模型,视频和类别,并且它们彼此之间具有“has_and_belongs_to_many”关系,那么当其中一个发生更改时,您如何执行触摸以使缓存无效?
您不能像使用一对多关系那样对它们进行“触摸”。现在,当我更改类别名称时,属于该类别的视频不知道更改,直到我使缓存无效。我的视图模板显示每个视频的类别名称。
如果您有 2 个模型,视频和类别,并且它们彼此之间具有“has_and_belongs_to_many”关系,那么当其中一个发生更改时,您如何执行触摸以使缓存无效?
您不能像使用一对多关系那样对它们进行“触摸”。现在,当我更改类别名称时,属于该类别的视频不知道更改,直到我使缓存无效。我的视图模板显示每个视频的类别名称。
在要更新的模型上,您可以执行以下操作:
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 时间戳都会更新。如果您希望在添加视频或从中删除视频时更新类别,您可以在类别类上执行相同的操作。
触摸只能在两种情况下使用。
记录在案
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 }