Expiring Cached Content in Rails - Part 1
Well, we've covered various ways to cache content in our Rails application, primarily with the goal of relieving the number of queries to the database. As I mentioned before, the fastest situation is where a request is made for a static page, which the server simply retrieves from the disk and sends to the user's browser. We can do this with Page Caching in Rails, which if you remember made it so that Rails would copy the output of an entire page to a static HTML file in the public directory of our application. Subsequent requests simply get that static page. Using the following code:
expire_page();
We were able have Rails erase that cache. The next fastest situation is where only Rails gets involved, perhaps doing some simple processing (such as putting templates together) and then spitting out the output. This situation is achieved by action and fragment caching, where Rails is invoked, but we try to avoid database calls that can be slow. While it's usually not a problem in development, when a web application scales and begins to experience higher traffic with more database records, queries can be slow. We had similar functions for expiring these caches when we wanted to:
expire_action() expire_fragment()
Again, these were all covered. When the caches are expired the database must be queried again to rebuild them. It becomes apparent pretty quickly that expiring cache files manually is really not a good option. So there are a couple of ways to accomplish such things, which I will cover in the next couple of posts.
The first, of course, are the functions that I mentioned above, which could easily be placed into any action in our Rails application to explicitly expire the cache file at our request. This is useful in some cases, such as if you wanted to create an action that allows you to empty cache files on demand. We could then navigate to a secret URI (which should probably require a password) that would run these functions to expire our cache files.
A better idea is to have these cache files expired only when the model that they draw data from changes. For example, in our example we are caching articles. Let's pretend that we make some changes to an article, we would then need to update the cached pages for our article list, as well as for that particular article. In this case, we might put a "sweeper" in place, which will automatically expire the cache files that we need to expire when changes are made to our Articles model. As it happens, my next post will be about these. I had used a method in that used aftersave() and afterdestroy() filters, before I discovered a raging case of Rails Envy. These guys have a much better method of using sweepers using Rails' built-in cache_sweepers. Good times, and a better way than my way was. So we'll take a look at that in the next post.
From there I want to talk about another method for eliminating cache files, which is kind of similar to our manual method with the "secret url" above. Using CRON, which is a Unix application that will run commands at given time intervals, we can have our cache files updated periodically based on time, not just when a model changes. In our example, let's say that our articles are ordered randomly, and whether or not any changes have been made, we want the cache file to expire every hour to ensure that the order changes for our visitors. In this case, a CRON job would be the answer, and I'll cover that in an upcoming post as well.