レールでフラグメントキャッシュを行うときに壊れたリンク
-
11-10-2019 - |
質問
コメントできる投稿、コメント、ユーザーのブログがあるとします。ユーザーは、などの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 %>
ジョンがニックをジョニーに変えたと仮定します - 彼のURLが変わる http:// localhost:3000/users/johnny. 。投稿やコメントでフラグメントキャッシュを行っているため、ジョンのコメントは、断片が期限切れになっていない限り、ジョンの間違ったURLを指します。この例では、ジョンによるコメントを含むすべての投稿を手動で触れたり期限切れにしたりすることが可能ですが、複雑なアプリケーションでは非常に複雑なクエリが必要であり、非常にエラーが発生しやすいようです。
ここでのベストプラクティスは何ですか? /users /johnの代わりに /users /13などの非セオフレンドリーなURLを使用する必要がありますか?または、キャッシュが期限切れになるまで古いURLのリストを保持しますか?私には見た目が良くないソリューションはありません。
編集:これは単純化された例にすぎないことに注意してください。この場合、投稿をクエリしてタッチするのは間違いなく非常に簡単です。しかし、複雑なアプリは、オブジェクト間の多くの関係を意味し、ユーザーへの参照があるすべてのオブジェクトを追跡することを難しくします。私はこれについて少し調査しました - Facebookはユーザー名を一度のみ設定できるため、この問題は存在しません。
解決
キャッシュされた投稿を期限切れにするのは複雑だとは思わない。スイーパーを設定します:
class UserSweeper < ActionController::Caching::Sweeper
observe User
def after_save(user)
user.comments.collect(&:post).each do |post|
expire_fragment post
end
end
他のヒント
たとえば、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
すべてのユーザーの投稿を更新するための1つのクエリ。本当に複雑ではありません。