在 Rails 中进行片段缓存时链接断开
假设有一个博客,其中包含帖子、评论和可以评论的用户。用户拥有 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。由于对帖子和评论进行了片段缓存,约翰的评论将指向约翰的错误 URL,除非该片段已过期。在此示例中,可以手动触摸或过期包含 John 评论的所有帖子,但在复杂的应用程序中,这将需要非常复杂的查询,并且似乎很容易出错。
这里的最佳实践是什么?我应该使用非 SEO 友好的 URL,例如 /users/13 而不是 /users/john 吗?或者保留旧 URL 列表直到缓存过期?没有解决方案对我来说看起来很好。
编辑:请注意,这只是一个简化的示例 - 在这种情况下查询帖子并触摸它们绝对非常简单。但复杂的应用程序意味着对象之间存在许多关系,这使得跟踪每个引用用户的对象变得困难。我对此进行了一些研究——Facebook 只允许设置你的用户名一次,所以这个问题不存在。
Suppose there is a blog with posts, comments and users which can comment. Users have SEO-friendly URLs such as http://localhost:3000/users/john (this can be easily done by using permalink_fu).
The model uses touch to simplify caching:
class Post
has_many :comments
end
class Comment
belongs_to :post, :touch=>true
end
And the view code would be something like this:
<%= 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 %>
Now suppose John changes his nick to Johnny -- his URL changes to http://localhost:3000/users/johnny. Because of doing fragment caching on posts and comments, John's comments will point to John's wrong URL unless the fragment is expired. It can be possible to manually touch or expire all posts that contain comments by John in this example, but in a complex application this would require very complex queries and seems very error-prone.
What's the best practice here? Should I use non-SEO-friendly URLs such as /users/13 instead of /users/john ? Or maybe keep a list of old URLs until the cache is expired? No solution looks good to me.
EDIT: Please note this is just a simplified example -- it's definitely very simple to query posts and touch them in this case. But a complex app implies many relationships among objects which makes it hard to track every object that has a reference to a user. I've researched a bit on this -- Facebook only allows setting your username once, so this problem doesn't exist.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不认为使缓存的帖子过期会很复杂。设置扫地机:
I don't see it would be complex to expire cached posts. Set up a sweeper:
我会使用 before_save 过滤器,例如
一个查询来更新每个用户的帖子。并不复杂。
I'd use a before_save filter for example
One query to update every user's post. Not really complex.