I have a rails 4 app using pundit gem for authorization. If I do russian-doll fragment caching like the code below, the conditional statement used for authorization will be also cached, which is not good, since edit/delete buttons should only be available for the post.user
.
What is the good way to get around this? Should I split the cache into smaller parts or is there a way to exclude some parts of the caching? What's the rails convention in this case?
index.html.erb
<% cache ["posts-index", @posts.map(&:id), @posts.map(&:updated_at).max, @posts.map {|post| post.user.profile.updated_at}.max] do %>
<%= render @posts %>
<% end %>
_post.html.erb
<% cache ['post', post, post.user.profile ] do %>
<div class="row>
<div class="col-md-2">
<%= link_to user_path(post.user) do %>
<%= image_tag post.user.avatar.url(:base_thumb), class: 'post-avatar' %>
<% end %>
</div>
<div class="col-md-8">
<span class="post-user-name"><%= post.user.full_name %></span>
<span class="post-updated"><%= local_time_ago(post.updated_at) %></span>
<div class="post-body">
<%= post.body %>
</div>
<div class="col-md-2" style="text-align:right;">
<!--############### THIS IS THE PART THAT SHOULD NOT BE CACHED #############-->
<% if policy(post).edit? && policy(post).delete? %>
<li class="dropdown">
<ul class = "dropdown-menu dropdown-menu-right">
<li>
<%= link_to "Edit Post", edit_post_path(post), remote: true, type: "button", 'data-toggle' => "modal", 'data-target' => "#updatepost_#{post.id}" %>
</li>
<li>
<a href="#" data-toggle="modal" role="button" data-target="#deletepost_<%= post.id %>">Delete Post</a>
</li>
</ul>
</li>
<% end %>
<!--########################## UNTIL HERE ############################-->
</div>
</div>
<div class = "row comment-top-row" style="padding-bottom:10px;">
<div class="col-md-12 post-comment-form">
<%= render partial: 'posts/post_comments/post_comment_form', locals: { post: post } %>
</div>
</div>
<div class = "row">
<div class="col-md-12 post-comment-insert-<%= post.id%>">
<%= render partial: 'posts/post_comments/post_comment', collection: post.post_comments.ordered.included, as: :post_comment, locals: {post: post} %>
</div>
</div>
<% if policy(post).edit? %>
<div class="modal fade updatepost" id="updatepost_<%= post.id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<!-- FORM GETS RENDERED HERE VIA JS -->
</div>
<% end %>
<% if policy(post).delete? %>
<div class="modal fade" id="deletepost_<%= post.id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
......
</div>
<% end %>
<% end %>
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…