2013-06-17 10 views
6

私のアプリ(Rails 4)ではユーザーが投稿に投票することができます。投稿をキャッシュすることは可能ですが、投票キャッシュをカスタマイズしてcurrent_userにパーソナライズされたものを表示することはできますか?たとえば、ユーザーが投票したかどうか。Rails 4でパーソナライズされたフラグメントをキャッシュするにはどうすればよいですか?

私はむしろこれを達成するためにhtml構造を変更しません。

オプション1:投票

これは、最も簡単な解決策と私は個人的に推奨しています一つですをキャッシュしません

# posts/_post.html.slim 
- cache post do 
    h1 = post.title 
    = post.text 
    = render 'votes/form', post: post 

# votes/_form.html.slim 
- if signed_in? && current_user.voted?(post) 
    = form_for current_user.votes.find_by(post: post), method: :delete do |f| 
    = f.submit 
- else 
    = form_for Vote.new do |f| 
    = f.submit 

答えて

6

あなたはここに2つのオプションがあります。あなたはこのような何かを持っているので、あなただけの動的なユーザー依存部分をキャッシュしません:

# posts/_post.html.slim 
- cache post do 
    h1 = post.title 
    = post.text 
= render 'votes/form', post: post # not cached 

オプション2:javascriptの

を使用するこのソリューションは、より複雑ですが、ベースキャンプはそれを行う方法実際にある(ただし、ほとんどもっと簡単な例があります)。両方の部分がページに表示されていますが、JavaScriptの1つを削除します。私はしかし、適切にあなたが新しいクエリを作成する必要はありませんので、IDを受け入れるようにvoted?方法を変更します

# posts/_post.html.slim 
- cache post do 
    h1 = post.title 
    = post.text 
    = render 'votes/form', post: post 

# votes/_form.html.slim 
div#votes{"data-id" => post.id} 
    .not_voted 
    = form_for current_user.votes.find_by(post: post), method: :delete do |f| 
     = f.submit 
    .voted 
    = form_for Vote.new do |f| 
     = f.submit 

# css 
.not_voted { 
    display:none; 
} 

# javascript (coffeescript) 
jQuery -> 
    if $('#votes').length 
    $.getScript('/posts/current/' + $('#votes').data('id')) 

# posts_controller.b 
def current 
    @post = Post.find(params[:id]) 
end 

# users/current.js.erb 
<% signed_in? && current_user.voted?(@post) %> 
    $('.voted').hide(); 
    $('.not_voted').show(); 
<% end %> 

:ここではjQueryとのCoffeeScriptを使用した例です。 http://railscasts.com/episodes/169-dynamic-page-caching-revised?view=asciicast

+0

ありがとうございます。 IDを受け取るように投票を変更すると、追加のクエリを実行できなくなります。それはすでにインスタンス変数として利用可能ではありませんか?あなたが必要とする唯一のクエリーは 'votes.where user_id = foo and post_id = foo'です。 – dee

+0

はい、javascriptソリューションでは '$ .getScript'がajaxリクエストをトリガーし、dbクエリを通じて' @ post'インスタンス変数を設定します。あなたが '@ post_id'を持つことができれば、このシナリオではこれがより速くなります。 – jokklan

+0

ありがとうございます。 1つの最後のコメント。あなたの最初の解決策は '= render @ posts'のようにコレクションをレンダリングできないことを意味します。なぜなら、投票のレンダリングは' _post'部分から起こり、キャッシュされるからです。コレクションをループして、各投稿を個別にキャッシュしてレンダリングし、キャッシュブロックの外側で '_vote'部分をレンダリングする必要があります。右? – dee

1

以下を試してください。これは、投票ごとに2つの異なる断片を作成し、投票ごとに投票しないようにします。それはその状態に従って読まれるでしょう。

# posts/_post.html.slim 
- cache [post, current_user.votes.find_by(post: post)]do 
    h1 = post.title 
    = post.text 
    = render 'votes/form', post: post 
関連する問題