1

Ich habe eine Rails 4 App mit Pandit Edelstein für die Genehmigung. Wenn ich das Caching von Russisch-Puppe-Fragmenten wie den unten stehenden Code mache, wird die für die Autorisierung verwendete Bedingungsanweisung ebenfalls zwischengespeichert, was nicht gut ist, da Schaltflächen zum Bearbeiten/Löschen nur für die post.user verfügbar sein sollten.Schienen, die einige Teile von Fragment Caching auslassen

Was ist der gute Weg, um dies zu umgehen? Soll ich den Cache in kleinere Teile aufteilen oder gibt es eine Möglichkeit, einige Teile des Cachings auszuschließen? Wie sieht die Rail-Konvention in diesem Fall aus?

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

Antwort

1

Russian Doll Caching ist einfach, aber praktische Möglichkeit für Caching, gibt es keine komplexen Optionen oder Konvention Teil des Fragments auszuschließen davon. Darüber hinaus ist es relativ zu Cache-Strategien. Hier sind zwei Strategien für diese benutzerspezifische Situation:

  1. Rearrange individuell und Cache Fragmente manuell, die ich nicht empfehlen. Weil es komplexer ist und die Vorteile von Russian Doll Caching nicht nutzt. Nicht so wartungsfreundlich. Hier ein Beispiel:

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 %> 
  1. Bevorzugte Art und Weise: In current_user als Teil von cache_key, was bedeutet, dass Sie so viele Fragment-Caches haben wie ungefähr Ihre Benutzer und die Fragmente werden automatisch ungültig, wenn der Beitrag oder der Benutzer ihren Fingerabdruck geändert hat. Dies ist eleganter und wartbarer. Hier ein Beispiel:

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 %> 
+0

abookyun ist diese zweite Art und Weise gut genug? Wird das Caching nicht seinen Zweck verlieren? Ich meine, wie Sie erwähnt haben, wird das Fragment für jeden einzelnen Benutzer neu geschrieben. Wird es auf lange Sicht nicht zu viel Speicher verbrauchen? –

+0

Bitte lesen Sie auch meinen vorherigen Kommentar. Ich habe vergessen zu erwähnen (vielleicht hast du gesehen), dass ich 'post_comment' in den' post' und 'post_comment_reply' verschachtelt habe, die in' post_comment' verschachtelt sind. Diese sollten auch nur vom 'current_user' bearbeitet werden können, also haben diese auch einige Teile, die nur für den' current_user' sichtbar sind. Muss ich das ändern oder "touch" kümmert sich darum? –

+0

@SzilardMagyar IMHO: Wie gesagt, es ist ein Strategie-Problem, nur wenn es die Möglichkeit gibt, schwere Anfragen wie verschachtelte Post- und Kommentarabfragen zu speichern. Ich denke, es ist gut genug, wenn die Vorlage häufig variiert, benötigen Sie eine andere Template-Caching-Struktur . Sie können diesen Artikel lesen, um zu erfahren, wie sich das Caching auf die Geschwindigkeit Ihrer App auswirkt https://signalvnoise.com/posts/3690-the-performance-impact-of-russian-doll-caching – abookyun

Verwandte Themen