2011-01-17 8 views
0

投稿、コメント、およびコメントを付けることができるブログがあるとします。ユーザーはhttp://localhost:3000/users/johnなどのSEOに優しいURLを持っています(これはpermalink_fuを使用すると簡単に行うことができます)。彼のURLが変更に -Railsでフラグメントキャッシュを実行するときに壊れたリンク

<%= 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 %> 

今すぐジョンを仮定がジョニーに彼のニックネームを変更します。このようなものになるだろう

class Post 
    has_many :comments 
end 

class Comment 
    belongs_to :post, :touch=>true 
end 

そしてビューコード:

モデルは、キャッシュを簡素化するためにタッチを使用していますhttp://localhost:3000/users/johnny。投稿とコメントにフラグメントキャッシングを行うため、Johnのコメントは、フラグメントが期限切れになっていない限り、Johnの間違ったURLを指し示します。この例では、Johnがコメントを含むすべての投稿を手動でタッチまたは有効期限切れにすることは可能ですが、複雑なアプリケーションでは非常に複雑なクエリが必要になり、エラーが発生しやすくなります。

ここでベストプラクティスは何ですか?/users/johnの代わりに/ users/13などのSEOに適していないURLを使用する必要がありますか?または、キャッシュが期限切れになるまで古いURLのリストを保持することもできますか?解決策は私には良く見えません。

編集:これはほんの単純化された例であることに注意してください。投稿を照会し、この場合はタッチするのは間違いなく簡単です。しかし、複雑なアプリケーションは、オブジェクト間の関係が多く、ユーザへの参照を持つすべてのオブジェクトを追跡することが難しいことを意味します。私はこれについて少し研究しました - Facebookはあなたのユーザー名を一度しか設定できないので、この問題は存在しません。

答えて

2

キャッシュされた投稿が期限切れになるのは複雑ではありません。スイーパーを設定してください:

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

def after_save(user) 
    user.comments.collect(&:post).each do |post| 
    expire_fragment post 
    end 
end 
+0

この例には適していますが、より大きなアプリでは難しいでしょう。私は単純化された例の解決策を探していないことを明確にするために質問を更新しました。 – Jose

+0

モデル間に関係が定義されていれば、スイーパーに追加することができれば、本当に問題はありません。ちなみに、あなたはGoogle friendly_idをしたいかもしれません。ユーザーのシナリオでは、キャッシュが期限切れになるまで追跡して新しいURLにリダイレクトします。 – mark

+0

friendly_idはスラグの履歴を保存します。私はそれについて知らなかったが、これは私が探していた解決策のようなものだったので、ありがとう、マーク! – Jose

0

は、私はすべてのユーザーの記事を更新するために、たとえば

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 

つのクエリをbefore_saveフィルタを使用すると思います。本当に複雑ではありません。

関連する問題