简体   繁体   中英

How do I add page caching to my Rails app for visitors?

Say I have a Rails 4.2 site on Heroku with many Posts. When a post is viewed, the application hits the database to get the post's data and associated data from other models. Visitors (non-logged-in users) to my website should see Posts without any customizations, so displaying these pages should not require accessing the database. How can I set up simple page or action caching (or an equivalent) for all visitors to my site, so the database is skipped? Could I also let a CDN take over rendering these pages?

For starters, take a look at the Rails caching guide . Both page and action caching have been removed from Rails.

You can try fragment caching, which will grab the generated HTML of the post and store it away, though you'll need a conditional based on whether or not there is a current_user .

A super-simple version might look like:

app/views/posts/show.html.erb

<% cache_unless (current_user, @post) do %>
  <%= @post.body %>
<% end %>

The cache method is going to be a read action if a cache exists for that post, and it will be a generate and write action if that cache doesn't exist.

Caching with an ActiveRecord object creates a key that includes updated_at by default, so if a post changes, the first visitor that loads the post will have a longer wait time, and every subsequent visitor will get the benefits of caching.

As for your other question, there are many other Ruby-based tools for serving static pages, and a review of all those is beyond my knowledge, and probably beyond the scope of this question. :)

Lanny Bose's answer really looks the best, but I'll add this link:

https://devcenter.heroku.com/articles/http-caching-ruby-rails#public-requests

The whole page is useful, but in particular it talks about marking requests as public or private. They are private by default, but if you mark it as public it allows pages to be served by an intermediary proxy cache.

The linked page talks about Rack::Cache + memcache as a proxy cache; I'm not sure if this still exists in rails 4.

This second heroku page talks about action caching, which could cache a specific action for you:

https://devcenter.heroku.com/articles/caching-strategies#action-caching

You don't really want caching here. You just want a conditional in both controller and view, like

# controller
if logged_in?
  @post = Post.find(params[:id])
  # load more records
end

# view
<% if @post %>
  <%= @post.title %>
  ...
<% else %>
  You're not logged in, blah blah.
<% end %>

.. assuming the controller is more than just loading a post record. I don't necessarily agree with conditionally loading the record as above, but your use case may require it.

Alternatively, if you DO require caching for performance reasons, you can just elegantly include the current user id in the fragment cache key like

<% cache "post-#{@post.id}-#{current_user ? current_user.id : 0}" do %>
  <% if logged_in? %>
  ... # expensive operations
  <% else %>
    Please login to see more..
  <% end %>
<% end %>

so that the cache works with the same code for users or anons.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM