Building on my previous post about caching where the method_cache plugin was introduced, today I’d like to introduce another Rails plugin that also deals with the caching problem. This time, it’s about caching views. It uses a technique called version caching. Version caching frees you from having to worry about writing code that expires your cache. For more info about version caching check Yasser Wahba’s blog post explaining version caching and how we used it. I’ve used version caching in my last 2 projects and found it quite useful and quite easy. The problem is that we used to repeat a lot of code violating DRY. It was so clear we had to do something about it. I’ve taken that code, refactored it and made it available as a Rails (v2.1.0) plugin available at GitHub. Check it here.

The plugin assumes using a cache store that uses LRU (least recently used) to handle when the cache becomes full and that also supports time caching. Cutting it short, it assumes we’re using memcached.

The plugin makes a couple of methods available in all controllers. These methods are

  • version_cache
  • time_cache
  • version_cache_key_part

The first 2 are the most important. time_cache as the name implies allows for time caching for a page. it can be used as follows

class WelcomeController < ApplicationController 
  time_cache :index => {:expiry => 5, :browser_cache_enabled => true}
  .
  .
  def index
    .
    .
  end
  .
  .
end

What we’ve just done is that we declared our intention of caching the index page of the welcome controller for 5 minutes in our cache store. In addition to the cache store, we declared our intention that we also want the page to be cached in the browser for the same period.

version_cache is the one responsible for tying the caching of a page to a model’s version. we can use it as follows

class ItemsController < ApplicationController
 
  version_cache Item, :associates => ["user"], :expiry => 5

end

By default, version_cache caches the show action unless an :action is provided. In the previous example we’re saying that we want to cache the show action of the items controller.

Item: the model whose objects versions are used.
:associates: an array of members on the model whose versions need to be updated as well when the the main model’s version is updated. i.e when an item is changed, its version is incremented and the item’s user’s version is also incremented. This is useful if we also cache users#show based on User model and changing an item reflects on the user’s page. :associates is optional
:expiry => an optional maximum time for the page to expire. if not specified, expiry will happen on the normal LRU
basis.

Models’ versions are maintained by the means of an observer. The observer has to observer the models we use and to be also declared in the environment.rb

version_cache_key_part is another method that allows a page to have multiple cached versions. We can use it as follows

class PostsController < ApplicationController
  .
  .
  version_cache Post, :associates => ["user"], :expiry => 5
  .
  .
  def show
  .
  end
 
  def version_cache_key_part
    if logged_in_user
      "logged_in"
    else
      "guest"
    end
  end

end

What just happened here is that based on some conditions we return a string that will be part of the cache key. Now we have 2 versions cached for the show page; one for logged in users and one for guests. You can have as many versions as you want based on whatever conditions as long as they return distinct strings.

To get the plugin

ruby script/plugin install git://github.com/humanzz/version_cache.git

Then use the plugin’s generator to generate the cache observer

ruby script/generate version_cache_observer Cache Model1 Model2

The first argument “Cache” is taken to be the observer’s name. Any arguments after that are taken to be the models that the observer will observe.


Version caching is a great caching technique and hopefully with the introduction of the plugin many developers will find it appealing and easy to use.

 

Technorati Tags: