在Rails中进行片段缓存时断开的链接

时间:2011-01-17 08:29:46

标签: ruby-on-rails caching permalinks fragment-caching

假设有一个博客,其中包含可以发表评论的帖子,评论和用户。用户拥有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只允许设置一次你的用户名,所以这个问题不存在。

2 个答案:

答案 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

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

相关问题