Rails Page Caching Explained

cache.png

Page caching is the simplest form of caching that Ruby on Rails offers. When invoked, page caching saves output to Rails’ public directory where it is subsequently served along with the other static pages. Of course this is advantageous for high traffic sites or pages that are slow to render. In most cases, page caching works without any config file editing. I, however, encountered a minor problem that prompted me to investigate this simple mechanism a bit further.

Rails Configuration

Just add one line to a controller to enable page caching:

class DemoController < ApplicationController
  caches_page :show

The caches_page() method instructs Rails to cache the output of the indicated actions. In the above example, Rails will save the output generated by the show action to the corresponding public directory. For example if a browser visits http://server/demo/show/123, cached output will reside in the file public/demo/show/123.html. For future requests, the web server will use this static file rather than running any Rails code.

If you would like Rails to expire the page, the easiest option is to call the method expire_page(). Arguments follow the same syntax as url_for. Under the hood, page expiry simply deletes the cached file. To expire the file created in the previous paragraph: expire_page :controller => "demo", :action =>, :id => 123

By default, caching directives are ignored unless RAILS_ENV=”production”. You can explicitly control caching for each environment by specifying config.action_controller.perform_caching = true in the appropriate environment file (e.g. “config/environments/development.rb”).

Web Server Configuration

Notice that Rails appends an “html” extension to cached pages. This extension allows the web server to treat the file like any other HTML file for determination of MIME type, permissions, etc. However, the extension also means that the web server must be configured to internally append “.html” to serve the cached page. Rails’ skeleton directory includes an Apache configuration file (public/.htaccess), and a Lighttpd configuration (config/lighttpd.conf), which do just that:

Apache Lighttpd
RewriteEngine On
RewriteRule ^([^.]+)$ $1.html [QSA]
server.modules = ( "mod_rewrite", ... )
url.rewrite += ( "^([^.]+)$" => "$1.html" )

Notice the regular expression common to both configurations: ^([^.]+)$. In English this translates to “if a request does not contain a period: ^([^.]+)$, then internally append ‘.html’ to that request: $1.html“.

My Original Problem: Firefox Ignoring Updates

I encountered what may be an isolated issue wherein Firefox 2 consistently failed to update pages whose contents expired via expire_page(). “about:cache” revealed that FireFox was setting a brief expiration time on static pages, and was using the old cached copy rather than requesting the current server copy. The workaround was easy enough – tell the web server to immediately expire cached pages. Continuing the above example, the Apache config should reside in public/demo/.htaccess, and the Lighttpd config should be added to lighttpd.conf:

Apache Lighttpd
ExpiresActive On
ExpiresDefault Now
server.modules = ( "mod_expire", ... )
$HTTP["url"] =~ "^/demo" {
  expire.url = ( "" => "access 0 seconds" )
}

These directives cause the web server to append Expires (HTTP 1.0) or Cache-Control (HTTP 1.1) headers that instruct the client to request the page anew for each display. This is less bandwidth-efficient, but that was not an issue for the intranet site I was working on.

Be Sociable, Share!

Tags: ,

2 Responses to “Rails Page Caching Explained”

  1. Web Server Configuration for mongrel ??

    I’m not using apache as well as Lighttpd,

    Can you please given me clear instruction for mongrel server, where should i make changes to tell the web server also look into cache directory for html files.

    Thanks in Advance,

    Sathish Kumar Sadhasivam

  2. la glutamina es mala para los riñones

    blog topic

Leave a Reply

Are you human? Answer this: *