Maintaining Lookup Data in Your Rails Application
Patrick Reagan, Former Development Director
Article Category:
Posted on
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