如何触摸HABTM关系

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

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

Touch只能在两种情况下使用。

记录在案

 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 

请注意,如果您还希望允许video触及类别,则必须找到避免“循环”更新的方法。

每个&find_each

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

 find_each(batch_size: 2000) { |video| video.touch } 

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

 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 

现在,只要在video中添加或删除某个类别,video的updated_at时间戳就会更新。 如果您希望在添加或删除video时更新类别,则可以对类别类执行相同的操作。