Cache only the main content in rails

2019-03-06 07:51发布

Using Rails 3.1.1 and Heroku.

I believe this should be a fairly easy fix but I cannot find (and easily verify) how to do this. I have a very slow controller (6 sec) Product#show, with lots of N+1 and other things I will have to solve.

The website is a two-column website (main-column and right-column) where the main content from Product#show is shown in one column and daily product are shown in the other, including a "Random Product from the Database".

What I want to do is to let the content in main-column that is created by Product#show be cached (and thus bypass the controller and win 6 seconds). I do, however, want the right column to be dynamic (and loaded for each page request).

If I use caches_page :show it will cache the entire website, including the right-column, which makes me have to expire the cache every day in order to be able to load a new Daily Product. Not a good solution.

If I use cache('product-show' + @product.slug) do it only caches the view (right?) and still have to go through the controller.

So, how can I solve this?

2条回答
女痞
2楼-- · 2019-03-06 08:48

You can achieve this with fragment caching like below:

def show

  if !fragment_exist?("main_content")
    @products = Product.all
    @users_count = User.count
  end

  @random_products = Product.order("RANDOM()").limit(10)

end

show.html.erb

<!--MAIN CONTENT-->
<% cache("main_content") do %>
    <%= @users_count %>
    <% @products.each do |product| %>
        <%= product.name %>
    <% end %>
<% end %>

<!--SIDE CONTENT-->
<% @random_products.each do %>
    <%= product.name %>  
<% end %>
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-03-06 08:53

Use fragment caching, and don't load things in the controller.

If you have a very complex query, let it live in the controller as a scope, and only evaluate it in the view.

If you have a complex process to do so the query must be executed, use a helper method.

If you manage to just load lazy queries in the controller, if the cache is hit none of them will be executed.

查看更多
登录 后发表回答