rails 从片段缓存中遗漏了一些部分
rails leaving out some parts from fragment caching
我有一个 rails 4 应用程序使用专家 gem 进行授权。如果我像下面的代码那样做俄罗斯娃娃片段缓存,用于授权的条件语句也会被缓存,这不好,因为 edit/delete 按钮应该只对 post.user
.
解决这个问题的好方法是什么?我应该将缓存分成更小的部分还是有办法排除缓存的某些部分?在这种情况下,rails 约定是什么?
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 %>
俄罗斯娃娃缓存是一种简单但方便的缓存方式,没有复杂的选项或约定可以从中排除部分片段。除此之外,它更多地与缓存策略相关。以下是针对此用户特定情况的两种策略:
- 单独重新排列并手动缓存片段,我不推荐这样做。因为它更复杂并且没有利用 Russian Doll Caching 的优势。也不那么可维护。这是一个例子:
index.html.erb
<% # pull out cache %>
<%= render @posts %>
_post.html.erb
<% cache post %>
<%= # first part %>
<% end %>
<% # without cache %>
<%= # user specific part %>
<% cache post %>
<%= # third part %>
<% end %>
- 首选方式:添加
current_user
作为 cache_key
的一部分,这意味着您将拥有与大约您的用户一样多的片段缓存,并且片段将在 post 或用户更改了他们的指纹。这更加优雅和可维护。这是一个例子:
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, current_user ] 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;">
<% 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 %>
</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 %>
我有一个 rails 4 应用程序使用专家 gem 进行授权。如果我像下面的代码那样做俄罗斯娃娃片段缓存,用于授权的条件语句也会被缓存,这不好,因为 edit/delete 按钮应该只对 post.user
.
解决这个问题的好方法是什么?我应该将缓存分成更小的部分还是有办法排除缓存的某些部分?在这种情况下,rails 约定是什么?
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 %>
俄罗斯娃娃缓存是一种简单但方便的缓存方式,没有复杂的选项或约定可以从中排除部分片段。除此之外,它更多地与缓存策略相关。以下是针对此用户特定情况的两种策略:
- 单独重新排列并手动缓存片段,我不推荐这样做。因为它更复杂并且没有利用 Russian Doll Caching 的优势。也不那么可维护。这是一个例子:
index.html.erb
<% # pull out cache %>
<%= render @posts %>
_post.html.erb
<% cache post %>
<%= # first part %>
<% end %>
<% # without cache %>
<%= # user specific part %>
<% cache post %>
<%= # third part %>
<% end %>
- 首选方式:添加
current_user
作为cache_key
的一部分,这意味着您将拥有与大约您的用户一样多的片段缓存,并且片段将在 post 或用户更改了他们的指纹。这更加优雅和可维护。这是一个例子:
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, current_user ] 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;">
<% 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 %>
</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 %>