rails4 double nested models russian-doll-caching

非 Y 不嫁゛ 提交于 2019-12-11 10:21:58

问题


I have the following structure in my rails4 app for the posts. Users can comment on the post and replies can be written on the comments. I'd like to use russian-doll-caching with auto-expiring keys on the page, but I don't know how I should exactly do it in this case.

Can sby tell me how to use it in this case?

Models:

#post.rb

belongs_to :user
has_many :post_comments, dependent: :destroy

#post_comments.rb

belongs_to :user
belongs_to :post
has_many :post_comment_replies, dependent: :destroy

#post_comment_replies.rb

belongs_to :user
belongs_to :post_comments

posts/index.html.erb

 <div class="post-index new-post-insert">
   <%= render @posts %>
 </div>

_post.html.erb

<%= post.body %>
<%= post.user.full_name %>
....
<%= render partial: 'posts/post_comments/post_comment', collection: post.post_comments.ordered.included, as: :post_comment, locals: {post: post} %>

_post_comment.html.erb

<%= post_comment.body %>
<%= post_comment.user.full_name %>
......
<%= render partial: 'posts/post_comment_replies/post_comment_reply', collection: post_comment.post_comment_replies.ordered.included, as: :post_comment_reply, locals: { post_comment: post_comment } %>

_post_comment_reply.html.erb

<%= post_comment_reply.user.full_name %>
<%= post_comment_reply.body %>

回答1:


You need to do a few things

Add touch to your belongs_to relations

The children and grandchildren of Post needs to touch their parents so that the updated_at column updates which in turn invalidates the cache keys.

#post_comments.rb

belongs_to :user
belongs_to :post, touch: true
has_many :post_comment_replies, dependent: :destroy

#post_comment_replies.rb

belongs_to :user
belongs_to :post_comments, touch: true

Add the cache command to your views

posts/index.html.erb

In the main list of posts we want to cache on the latest updated_at for posts and the latest updated_at for the respective user.

 <div class="post-index new-post-insert">
    <% cache ["posts", @posts.maximum(:updated_at).to_i, @posts.map {|p| p.user.try(:updated_at).to_i}.max] %>
     <%= render @posts %>
    <% end %>
 </div>

_post.html.erb

<% cache ["postlist", post, post.user] %>
  <%= post.body %>
  <%= post.user.full_name %>
  ....
  <%= render partial: 'posts/post_comments/post_comment', collection: post.post_comments.ordered.included, as: :post_comment, locals: {post: post} %>
<% end %>

_post_comment.html.erb

<% cache ["postcommentlist", post_comment, post_comment.user] %>
  <%= post_comment.body %>
  <%= post_comment.user.full_name %>
  ......
  <%= render partial: 'posts/post_comment_replies/post_comment_reply', collection: post_comment.post_comment_replies.ordered.included, as: :post_comment_reply, locals: { post_comment: post_comment } %>
<% end %>

_post_comment_reply.html.erb

<% cache ["postcommentreplylist", post_comment_reply, post_comment_reply.user] %>
  <%= post_comment_reply.user.full_name %>
  <%= post_comment_reply.body %>
<% end %>

This could be improved by using cached: true in the render partial function. However since we want to expire the cache if the user changes their username it becomes a bit tricky.

You can do that if you override all the models cache_key functions.

Why should I use cached: true in render partial?

Instead of calling cache inside each partial (like we do above) we could do

<%= render partial: 'posts/post_comments/post_comment', collection: post.post_comments, cached: true %>

If we only need to cache on the post_comment´s updated_at.

The difference between the two are that when we cache inside the partial Rails issues a get command to the cachestore (e.g. memcache) one time per object. Therefore if you have 50 postcomments, there will be 50 separate requests to memcached to retrieve all.

But if we instead use cached: true in the render call Rails will issue a multi_get request to memcached and retrieve all 50 objects in one request. Thus improving page loadtime. In tests we have conducted in our production env. it decreased the page loadtime by ~50ms - ~200ms depending on the amount of data.



来源:https://stackoverflow.com/questions/36340017/rails4-double-nested-models-russian-doll-caching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!