0

假设有一个博客,其中包含帖子、评论和可以评论的用户。用户拥有对 SEO 友好的 URL,例如http://localhost:3000/users/john(这可以通过使用 permalink_fu 轻松完成)。

该模型使用触摸来简化缓存:

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——他的 URL 更改为http://localhost:3000/users/johnny。由于对帖子和评论进行片段缓存,除非片段过期,否则 John 的评论将指向 John 的错误 URL。在此示例中,可以手动触摸或过期包含 John 评论的所有帖子,但在复杂的应用程序中,这将需要非常复杂的查询,并且看起来很容易出错。

这里的最佳做法是什么?我应该使用非 SEO 友好的 URL,例如 /users/13 而不是 /users/john 吗?或者可能保留旧 URL 列表直到缓存过期?没有解决方案对我来说很好。

编辑:请注意这只是一个简化的例子——在这种情况下查询帖子并触摸它们绝对非常简单。但是一个复杂的应用程序意味着对象之间的许多关系,这使得很难跟踪每个引用用户的对象。我对此进行了一些研究——Facebook只允许设置你的用户名一次,所以这个问题不存在。

4

2 回答 2

2

我不认为过期缓存帖子会很复杂。设置扫地机:

class UserSweeper < ActionController::Caching::Sweeper
observe User

def after_save(user)
  user.comments.collect(&:post).each do |post|
    expire_fragment post
  end
end
于 2011-01-17T09:00:07.463 回答
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

一个查询来更新每个用户的帖子。不是很复杂。

于 2011-01-17T08:57:59.567 回答