Simplistic Enumerations for ActiveRecord

Invariably, in almost every application there happen to be lists of data items that are immutable, just for reference. It could be colors, the four seasons, continents, the states of your country, kinds or types of this and that. These items are almost like constants. As accessible as they are through the ordinary ActiveRecord API, it seems an utter waste to hit the database again and again, for data that won’t change however often you request it.

Of course, the Rails community recognized early on that some data are more constant than others and over the years several plugins have been published that add cached and easily accessible enumerations to ActiveRecord. Some of these additions are quite complicated or befuddle ActiveRecord by not backing the enumeration values with real database objects. My experience has been that these attempted optimizations result in bizarre behavior when I did interesting things with ActiveRecord such as multiply nested named scopes plus custom SQL.

So, I thought a basic, no, simplistic, version of enumerations is called for. Here’s how it looks:

class Color < ActiveRecord::Base
  enumerates do |e|
    e.value :name => 'red'
    e.value :name => 'green'
    e.value :name => 'blue'
  end
end

Color[:green]
Color.find_by_name('red')
Color.find_by_name!(:red)
Color.all
Color.count
Color.reload

e.value :name => 'red'

ensures that a Color object with name ‘red’ exists, if it does not, one is created.

Caveats

Although there is a #reload method defined on enumeration models, i.e. Color.reload, it is very unwise to use it. The point is that this method only affects a single server process and you most likely have many of them.

So, if you need to change enumeration values, the only way to do it is to treat it like an update to your application code.

Getting it

  • github
  • $ sudo gem install mschuerig-easy_enums

Let your Rails app know about it

In the appropriate place in config/environment.rb add

config.gem "mschuerig-easy_enums", :lib => 'easy_enums'