假设有一个博客,其中包含可以发表评论的帖子,评论和用户。用户拥有SEO友好的URL,例如http://localhost:3000/users/john(这可以通过使用permalink_fu轻松完成)。
该模型使用touch来简化缓存:
class Post
has_many :comments
end
class Comment
belongs_to :post, :touch=>true
end
视图代码将是这样的:
<%= cache @post do %>
<h1><%= @post.title %></h1>
<%= @post.content %>
<%= @post.comments.each do |comment| %>
<%= link_to h(comment.user), comment.user %> said:
<%= comment.content %>
<% end %>
<% end %>
现在假设John将他的昵称更改为Johnny - 他的网址更改为http://localhost:3000/users/johnny。由于在帖子和评论上进行片段缓存,John的评论将指向John的错误URL,除非片段已过期。在此示例中,可以手动触摸或过期包含John的注释的所有帖子,但在复杂的应用程序中,这将需要非常复杂的查询,并且似乎非常容易出错。
这里的最佳做法是什么?我应该使用非SEO友好的URL,例如/ users / 13而不是/ users / john吗?或者在缓存过期之前保留旧URL列表?没有解决方案对我来说很好。
编辑:请注意这只是一个简单的例子 - 在这种情况下查询帖子并触摸它们肯定非常简单。但是复杂的应用程序意味着对象之间存在许多关系,这使得很难跟踪每个引用用户的对象。我已经研究了一下 - Facebook只允许设置一次你的用户名,所以这个问题不存在。
答案 0 :(得分:2)
我认为缓存帖子到期并不复杂。设立扫地机:
class UserSweeper < ActionController::Caching::Sweeper
observe User
def after_save(user)
user.comments.collect(&:post).each do |post|
expire_fragment post
end
end
答案 1 :(得分:0)
我使用了一个before_save过滤器,例如
class User
has_many :posts
before_save :touch_posts
private
def touch_posts
Post.update_all({:updated_at => Time.now}, {:user_id => self.id}) if self.login_changed?
true
end
end
更新每个用户帖子的一个查询。不是很复杂。