Caching in Rails

The information in this card is only relevant for Rails 2.3-era apps.


This note gives a quick introduction into caching methods (page caching, action caching and fragment caching) in rails and describes some specific problems and solutions.

The descriptions below are valid for Rails 2 and 3. Recently, caching with timestamp- or content-based keys has become more popular which saves you the pain of invalidating stale caches.

How to enable/disable caching

To enable or disable caching in rails you can use the following option in your environment config file:

config.action_controller.perform_caching = true

Page Caching

With Page Caching the rendered source code will be saved as html file. When a user has a cache hit for the requested page, the html file will be directly delivered from your webserver without going through your rails application stack. Be aware that no hooks like authentication will be invoked and no parameters will be taken into consideration for cache key generation! If there aren't any params that would change the output you have a really fast caching method in your hands.

To use page caching you can do something like that

class JobsController < ApplicationController

  caches_page :index

  def index
    @jobs = Jobs.all
  end

end

which will cache the whole output for the index action.

To clear the page cache for the index action you can use the following command in your controller:

expire_page :action => :index

Action Caching

Action Caching works like Page Caching but the rails application stack will be executed. That means you can use before filters (e.g. for authentication).

class JobsController < ApplicationController

  caches_action :index

  def index
    @jobs = Jobs.all
  end

end

To clear the cache for a specific action, use something like this:

expire_action :action => :index

Options like :cache_path, :if, :unless, ... help you with setting up a more specific cache strategy that fullfil your needs. For example you can use the :cache_path option to generate a cache id that takes the params hash or your session data into consideration. The following example demonstrates how you could include params to generate the cache path:

class JobsController < ApplicationController

  caches_action :index, :cache_path => :index_cache_path.to_proc

  def index
    @jobs = Jobs.find_by_name(params[:name])
  end
  
  def index_cache_path
    "jobs/" + params[:name]
  end

end

Fragment Caching

Fragment Caching allows you to cache specific parts inside your view templates.

<p>List of jobs:</p>

<% cache(:action => 'index', :action_suffix => 'all_jobs') do %>
  <%= do_some_render_intensive_stuff %>
<% end %>

<p>Other html stuff</p>

If there is only one fragment to cache you can call the cache method inside your view without any parameters. Then it will automatically use the current controller and action name to build the fragment cache key.

To clear the cache for a specific fragment you can use something like this:

expire_fragment(:controller => 'jobs', :action => 'index', :action_suffix => 'all_jobs')

Further readings

A more detailed introduction for caching in Rails can be found in the Ruby on Rails guide for caching Show archive.org snapshot . It also describes how you can use cache sweepers Show archive.org snapshot that observe your model and sweep your cache after something has changed.

Ulrich Berkmueller About 13 years ago