Caching with extra parameters
While premature optimization is often a serious problem for developers, there are certain places where it pays to think ahead. Rails provides a wonderful interface for caching, but there are a couple of key points to keep in mind to make sure you can take advantage of it. In this article, we will talk about query parameters and caching and how to easily move them into the url.
This issue came up during development of an application for a client. The typical access pattern involves mostly reads of a relatively small number of pages. This type of access pattern lends itself really well to caching. Unfortunately, the application behaves differently according to the domain that it is called from.
Here’s an example: Let’s say I sign up for the service and tell the site I want to use “elevatedrails” as my domain name. When somebody accesses http://elevatedrails.domain.com, the rails application inspects the hostname, and finds an active record object called Website. From there, all actions inside the controllers use the Website object.
Doing that is pretty straightforward, we just have a before_filter that looks at the domain and finds the Website by subdomain. Unfortunately, this means the default caching strategy won’t work. To Rails, http://elevatedrails.domain.com/songs/show/ looks identical to http://yourdomain.domain.com/songs/show/. This means that by default, caching would cache the first website shown and any domain name would show that result. Obviously, that would be a branding nightmare.
Fortunately, the fix is simple. Just move the id of the website into the URL. There are two steps that you need to make this happen. The first is that the URL needs to always be in the calls to link_to and url_for. That is a pain to do manually, but is trivial using default_url_options
def default_url_options(options)
{:website_id=>@website.id} if @website
end
Once you have done that, you can add a route to the routes file that looks like map.connect '/songs/:website_id/:action/:id', :controller=>"songs". Restart your server and all of your routes should now look like http://elevatedrails.domain.com/songs/1/show, which is caching friendly. Of course, if you have additional parameters, you can add those to the route as well.
This simple step allows you to turn on the rails page caching, significantly boosting performance.
Posted by Mike Mangino on Thursday, October 05, 2006