Page Caching in Rails
The first type of caching content in Rails that I wanted to post about is called Page Caching. When using page caching, you are telling Rails to cache the output of an entire web page. As you can imagine, Rails will create a static HTML copy of the page to be cached, and stores that file in the “public” folder of your Rails application. The next time that page is accessed, Rails doesn’t even get involved, but rather the cached page is served to the user as if it were static HTML content. From the standpoint of speeding things up, this method will give the most performance gains as there is no script processing at all. However, there are drawbacks to page caching that developers should be aware of, primarily because Rails does nothing but serve the static page once cached. This means that any user-specific content or dynamic content (such as today’s date) is also cached and re-displayed as static data. As you can imagine, in the case of displaying today’s date on a page, that will cause the date to always show the day that the page was cached.
First, let’s go through how to do page caching, since it is almost too easy. Let’s say that you have an action called “list” in your controller called “articles”, which would be accessible at the URL /articles/list. If you were going to cache the output of this page you would put the following code at the top of your controller:
caches_page :list
That’s it. The next time you go to the URL /articles/list Rails will automatically create a static HTML file of the output, and store it as /articles/list.html in the public folder of the Rails application. As I mentioned, the next time a request is made for the URL /articles/list Rails will not even be invoked at all, but rather the HTML document will be served. Because of that fact that Rails does not even come into play, this leads to an interesting problem, and that is how to deal with Pagination.
Let’s say that our list action has pagination on it, and we want to also cache the various pages. The first problem is that when you do just plain old pagination, you usually end up with URLs like /articles/list?page=2. Since Rails does not get involved, and therefor no script is run, it ignores the extra parameters after the action name, which in this case is the parameter telling which page we want. As you may have guessed, Rails builds it’s page cache files based on the URL that is requested, so that if we were looking at a specific article, let’s say with the URL of /articles/show/5 it would create an HTML file called /articles/show/5.html when it caches that page. In this case, we passed the variable of the article to be shown in the URL, which is what we need to do for pagination on our “list” action in order to get caching to work.
To do this, we will need to create a new route in our routes.rb file, so that Rails recognizes the URL that we are requesting. Since we want to replace /articles/list?page=2 with /articles/list/2 as our URL, we will create the following route:
map.connect 'articles/list/:page', :controller => 'articles', :action => 'list'
Basically we have told Rails that anytime a request comes through that starts with /articles/list/ and ends with a number to pass that number along as the page parameter. Now the URL that Rails will cache when we pagination will be /articles/list/2.html for the second page of our list. Hopefully that is not too confusing, but the moral of the story is that since Rails uses URL’s to determine the cache files, and it ignores parameters that are passed in a URL (anything after the ?), we need to have clean URLs to start with. Not that this is a bad thing since clean URL’s are more search engine friendly anyway, and just generally good form.
Expiring Page Caches
As I mentioned before, it is simple to create cache files. However, odds are your pages will need to change quite often or you wouldn’t be using Rails to begin with. While I will have a post dedicated to expiring caches later on here, I wanted to include how to expire each type of cache. Let’s say that we want to expire the cache that we created above for our article list. To do that, we call another function in our controller as follows:
expire_page(:controller => 'articles', :action => 'list')
Remember how we used cachepage before to create a page cache? Now we use expirepage to destroy that cache file when we want to. Again, I will post more about expiring later as we look at that in more detail, but keep in mind that you would want to call this function any time that you want to destroy the cache file. Using our example from above when we showed a specific article at the URL /articles/show/5, we would expire that cache by calling expire_page like this:
expire_page(:controller => 'articles', :action => 'show', :id => 5)
Additionally, you could just go into the “public” folder of your Rails application and manually delete the cache files, which will force Rails to create new ones the new time a request is made. I’ll post more about caching strategies and options in later posts.

Connect with us