rails caching

Posted on April 11, 2013 ruby rails


  • HTTP Caching: Uses HTTP headers to instruct browsers on server side caching.
  • Page Caching: Cache the entire page to disk and serve directly from the web server like Nginx.
  • Action Caching: Runs through the rails pipeline and runs before_filters but returns cached results from disk like page caching.
  • Fragment Caching: Store parts of views in the cache.
  • Rails.cache: In memory server side cache.

Page Caching

class ProductsController < ActionController caches_page :index

def index @products = Products.all end end

  • /products will generate a file called products.html.gz. NGINX will efficiently serve this static file
  • by default pages are cached in /public

To expire a page you call expire_page in the action that would invalidate the cache.

class ProductsController < ActionController caches_page :index

def index @products = Products.all end

def create expire_page :action => :index end end

Nginx can serve compressed content directly from disk by enabled gzip_static

  location / {
    gzip_static on;

Page caching ignores parameters like /products?page=1. If someone requests /products?page=2 they will get the cached first page. A workaround is to use a route like /products/page/1

Action Caching

This is good for pages that restrict access in some way. Incoming request does go from webserver to rails stack. Before filters are run to allow for things like authentication. Instead of expire_page you use expire_action.

class ProductsController < ActionController
  before_filter :authenticate
  caches_action :index

  def index
    @products = Product.all

  def create
    expire_action :action => :index

Fragment Caching

Add cache “key” to your view to cache a fragment. You can use the updated_at timestamp to signal when to invalidate the cache.

<%= cache "post-#{@post.id}", @post.updated_at.to_i do %>
  <h1><%= @post.title %></h1>
  <p><%= @post.content %></p>
<% end %>

If you touch a post it will update the timestamp.


  class Comment < ActiveRecord::Base
    belongs_to :post, :touch => true

Rails Cache

  Rails.cache.write('foo', 'bar')