has_enumeration

Overview

has_enumeration adds support for enumerated types to ActiveRecord. The values of an enumerated attribute are represented as symbols regardless of the attribute's underlying representation in the database. Predicates (e.g. car.color.red?) are provided for each value of the enumerated type.

Defining Enumerated Attributes

Enumerated attributes are declared in the model's class definition with the has_enumeration class method. For example:

class Car < ActiveRecord::Base
  has_enumeration :color, [:red, :green, :blue]
end

The above definition assumes that the color attribute is stored as a string and that its values in the database match those obtained by calling to_s on their corresponding symbols. I.e., :red is stored as 'red'.

If the underlying column is not a string or its values do not match the string version of the enumeration's symbols, then the mapping between symbols and their underlying values may be provided as a hash:

class Car < ActiveRecord::Base
  has_enumeration :color, :red => 1, :green => 2, :blue => 3
end

By default, the underlying attribute is assumed to have the same name as the enumeration. If this is not the case, the name of the underlying attibute may be provided with the :attribute option:

class Car < ActiveRecord::Base
  has_enumeration :color, {:red => 1, :green => 2, :blue => 3},
    :attribute => :hue
end

Using Enumerated Attributes

Assignment

Enumerated attributes are assigned using symbols:

car = Car.new(:color => :red)
car.color = :blue

The symbols are coerced into an instance of a nested class (Car::Color in this example) that is created by has_enumeration. If for some reason you need to avoid the type coercion, you can assign a value of that class directly:

car.color = Car::Color.from_sym(:green)

Querying

When constructing queries referencing the enumerated attribute, use the symbol as its value:

Car.find(:all, :conditions => {:color => :red})

has_enumeration supports Rails 3 and is aware of the model's underlying Arel representation:

Car.where(:color => :red)
Car.where(Car.arel_table[:color].not_in([:red, :green]))

If you are using MetaWhere, has_enumeration plays nicely with it:

# This example requires the meta_where:
Car.where(:color.not_in => [:red, :green])

Testing Values

The primary means of interacting with enumerated attributes is through the predicate methods that are automatically generated for each value in the enumeration:

car = Car.new(:color => :red)
car.color.red?
# => true
car.color.green?
# => false

If the value of the attribute is needed as a symbol, e.g., for direct comparison, it can be retrieved with to_sym:

car.color.to_sym
# => :red

Installation

has_enumeration is packaged as a gem:

gem install has_enumeration

Rails 3

To use has_enumeration with Rails 3, simply add it to your application's Gemfile:

gem 'has_enumeration'

Rails 2.x

To use has_enumeration with Rails 2, add it to your application's environment.rb file:

config.gem 'has_enumeration'

Supported Configurations

has_enumeration has been tested with the following versions of ActiveRecord:

  • 2.3.10
  • 3.0.1
  • 3.0.3

and the following Ruby implementations:

  • 1.8.7-p302
  • 1.9.2-p0
  • JRuby 1.5.5
  • Rubinius 1.1.0

Getting the Latest

has_enumeration is hosted on github at http://github.com/gregspurrier/has_enumeration.

You can make a local clone of the repository with the following command:

git clone git://github.com/gregspurrier/has_enumeration.git

License

has_enumeration is Copyright 2010 by Greg Spurrier. It is released under the MIT License. Please see LICENSE.txt for details.