【问题标题】:How to touch a HABTM relation如何接触 HABTM 关系
【发布时间】:2013-05-25 10:28:42
【问题描述】:

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

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

【问题讨论】:

  • 我认为 HABTM 不存在,因为它的性能可能不会很好。你有什么理由不能使用回调来做同样的事情吗?
  • 不,我会用任何东西来让它工作。你能给我一个关于如何用回调触摸的方向吗?
  • 放弃HABTM并使用has_many :through
  • 视频模型中是否缓存了类别名称?你能写出这个问题来使它更明确吗?
  • 我不需要为此创建另一个模型吗?我很好奇@d_ethier 在使用回调时所说的话。任何人都可以对此发表评论吗?谢谢大家

标签: ruby-on-rails caching activerecord


【解决方案1】:

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

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

【讨论】:

  • 正是我想要的,谢谢!我想在添加或删除类别时更改视频,而不是在更新类别本身时。
【解决方案2】:

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

记录在案

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 }

【讨论】:

  • 这很有帮助,谢谢。幸运的是,目前我不需要视频来触及类别:)
  • touch_videos 应该是videos.each(&amp;:touch)
  • 我也会避免在视频类中使用each。相反.. update_all(updated_at: Time.now) 这将只是一个 SQL 查询,each 将是 n+1
  • 感谢 basgys 和李。你帮了我很多。
  • 注意:touchupdate_all 不会触发验证或回调,touch 除外,因为它会触发 after touch 回调但不会触发其他回调。如果在一个关系上执行了touch,它也触及了您的原始模型,您将陷入循环更新无限循环。 IOW,touch 将触发级联 touch 如果在与触摸对象上的 touch: true 的任何关系中指定。在上面的例子中使用update_attributes 会导致循环更新,如果你尝试从视频-> 类别中进行相同的更新。使用update_all 不会级联。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多