Maintaining Lookup Data in Your Rails Application

Early last year, Dave Thomas gave a great talk on Metaprogramming in Ruby which he reprised last week at April's NovaRUG meeting. One of the quick examples he gave during the talk inspired me to work on an idea that began as a submission to Advanced Rails Recipes, turned into a Rails plugin, and which I just re-released as a gem. Basically, it allows you to cache the lookup data for your Rails models when your application loads.

Installation

Since we're hosting our code on RubyForge, a simple gem install will fetch the latest version:

 sudo gem install constant_cache 

Usage

Assuming that your application has a Status model with data that looks like this:

 mysql> select * from statuses; +----+----------+ | id | name | +----+----------+ | 1 | Pending | | 2 | Active | | 3 | Disabled | +----+----------+ 3 rows in set (0.00 sec) 

All that's needed is to include the gem in your model class and instruct it to cache its data:

 require 'constant_cache' class Status caches_constants end 

Status data is now available as constants on the class:

 $ ./script/console Loading development environment (Rails 2.0.2) >> Status.find(:all).map {|s| [s.id, s.name] } => [[1, "Pending"], [2, "Active"], [3, "Disabled"]] >> Status::PENDING => #Status id: 1, name: "Pending" >> Status::ACTIVE => #Status id: 2, name: "Active" 

Since the constants point to ActiveRecord instances, the real value comes when you want to use them as part of an association:

 user = User.create!(:username => 'preagan', :status => Status::PENDING) 

The gem relies on a name column in your database, but can be configured to use something else as needed:

 class Status caches_constants :key => :slug end 

Other configuration options are available, see the README file for more information.

Future Additions

Right now, the gem only handles caching data that exists in the database when the application is loaded, it isn't able to handle cases when the data changes (e.g. a record is deleted, or a name is changed). I plan to handle these cases in a future release. Feedback and patches are always welcome

Patrick is development director in Viget's Boulder, CO, office. He writes clean Ruby code and automates system infrastructure for clients such as Shure and Volunteers of America.

More posts by Patrick