如何触摸HABTM关系

时间:2013-05-30 00:37:40

标签: ruby-on-rails caching activerecord

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

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

2 个答案:

答案 0 :(得分:30)

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

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时间戳就会更新。如果您希望在添加或删除视频时更新类别,则可以对类别类执行相同的操作。

答案 1 :(得分:12)

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

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

每个&amp; find_each

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

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