A class based enumerator utility for Ruby on Rails
Pull request Compare This branch is 311 commits behind AgilionApps:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



ClassyEnum is a Ruby on Rails gem that adds class-based enumerator functionality to ActiveRecord attributes.


Rails: Any version of Rails 2.3.x or Rails 3.×. (Older versions of Rails may work, but have not been tested)

Ruby: Ruby 1.8.7 and 1.9.2.


The gem is hosted at rubygems.org and can be installed with: gem install classy_enum

Example Usage

The most common use for ClassyEnum is to replace database lookup tables where the content and behavior is mostly static and has multiple “types”. In this example, I have an ActiveRecord model called Alarm with an attribute called priority. Priority is stored as a string (VARCHAR) type in the database and is converted to an enum value when requested.

1. Generate the Enum

The fastest way to get up and running with ClassyEnum is to use the built-in Rails generator like so:

Rails 2.3.x:

script/generate classy_enum Priority low medium high

Rails 3.x

rails g classy_enum Priority low medium high

A new enum template file will be created at app/enums/priority.rb that will look like:

class Priority < ClassyEnum::Base
  enum_classes :low, :medium, :high

class PriorityLow < Priority

class PriorityMedium < Priority

class PriorityHigh < Priority

The enum_classes macro will add all the ClassyEnum behavior, which is described further down in this document.

2. Customize the Enum

The generator creates a default setup, but each enum member can be changed to fit your needs.

Using the enum_classes method, I have defined three priority levels: low, medium, and high. Each priority level can have different properties and methods associated with it.

I would like to add a method called send_email? that all member subclasses respond to. By default this method will return false, but will be overridden for high priority alarms to return true.

class Priority < ClassyEnum::Base
  enum_classes :low, :medium, :high

  def send_email?

class PriorityHigh < Priority
  def send_email?

Note: Defining the subclasses within your enum file is only required when you will be overriding behavior and/or properties. The member subclasses still exist without being defined here because ClassyEnum.enum_classes automatically creates a class for each member. The generator only creates these subclass definitions for convenience, but they can be deleted as shown in this example.

3. Setup the ActiveRecord model

My ActiveRecord Alarm model needs a text field that will store a string representing the enum member. An example model schema might look something like:

create_table "alarms", :force => true do |t|
  t.string   "priority"

Then in my model I’ve added a line that calls classy_enum_attr with a single argument representing the enum I want to associate with my model. I am also delegating the send_email? method to my Priority enum class.

class Alarm < ActiveRecord::Base
  classy_enum_attr :priority

  delegate :send_email?, :to => :priority

With this setup, I can now do the following:

@alarm = Alarm.create(:priority => :medium)

@alarm.priority  # => PriorityMedium
@alarm.priority.is? :medium # => true
@alarm.priority.to_s # => 'medium'
@alarm.priority.name # => 'Medium'

# Should this alarm send an email?
@alarm.send_email? # => false
@alarm.priority = :high
@alarm.send_email? # => true

The enum field works like any other model attribute. It can be mass-assigned using update_attribute(s).

Special Cases

What if your enum class name is not the same as your model’s attribute name? No problem! Just use a second arugment in classy_enum_attr to declare the attribute name. In this case, the model’s attribute is called alarm_priority.

class Alarm < ActiveRecord::Base
  classy_enum_attr :priority, :alarm_priority

@alarm = Alarm.create(:alarm_priority => :medium)
@alarm.alarm_priority  # => PriorityMedium

Model Validation

An ActiveRecord validator validates_inclusion_of :field, :in => ENUM.all, :allow_nil => true is automatically added to your model when you use classy_enum_attr.

If your enum only has members low, mediume, and high, then the following validation behavior would be expected:

@alarm = Alarm.new(:priority => :really_high)
@alarm.valid? # => false
@alarm.priority = :high
@alarm.valid? # => true

Working with ClassyEnum outside of ActiveRecord

While ClassyEnum was designed to be used directly with ActiveRecord, it can also be used outside of it. Here are some examples based on the enum class defined earlier in this document.

Instantiate an enum member subclass PriorityLow

# These statements are all equivalent
low = Priority.build(:low)
low = Priority.build('low)
low = Priority.find(:low)
low = PriorityLow.new

Get a list of the valid enum options

Priority.valid_options # => low, mediume, high

Formtastic Support

To add ClassyEnum support to Formtastic, add the following to your formtastic.rb initializer (config/initializers/formtastic.rb):

Formtastic::SemanticFormHelper.builder = ClassyEnum::SemanticFormBuilder

Then in your Formtastic view forms, use this syntax: <%= f.input :priority, :as => :enum_select %>


Copyright © 2011 Peter Brown. See LICENSE for details.