public
Description: Adds support for declaring an ActiveRecord class as an enumeration
Homepage: http://www.pluginaweek.org
Clone URL: git://github.com/pluginaweek/enumerate_by.git
name age message
file .gitignore Fri Jul 04 15:49:48 -0700 2008 Ignore test/app_root/script [obrie]
file CHANGELOG.rdoc Loading commit data...
file LICENSE Sun May 04 14:35:16 -0700 2008 Move to trunk Add support for overriding the un... [obrie]
file README.rdoc Sun Sep 07 07:34:13 -0700 2008 Add notes on camelcase/underscore lookups [obrie]
file Rakefile
file init.rb Thu Jul 12 11:28:04 -0700 2007 Initial release [obrie]
directory lib/
directory test/
README.rdoc

acts_as_enumeration

acts_as_enumeration adds support for declaring an ActiveRecord class as an enumeration.

Resources

API

Bugs

Development

Source

  • git://github.com/pluginaweek/acts_as_enumeration.git

Description

Support for enumerations is dependent on the type of database you use. For example, MySQL has native support for the enum data type. However, there is no native Rails support for defining enumerations and the associations between it and other models in the application.

acts_as_enumeration adds support for enumerations in Rails by providing methods for interacting with records in a table as if they were values in an enumeration. The important thing to remember about this plugin is that you always use the enumeration attributes within the application and know that the enumeration ids are stored in the database. This means that you would use ‘red’ everywhere in your code when referencing the ‘red’ enumeration identifier, but it would always be stored in the database with the integer value of 1.

In addition, remember that your enumerations act almost exactly like regular ActiveRecord models. This means that you can define validations, enumerations, etc. There is limited support for advanced finder options, addressed by the in_memory branch discussed later on.

Usage

Default enumeration

  class Color < ActiveRecord::Base
    acts_as_enumeration

    create :id => 1, :name => 'red'
    create :id => 2, :name => 'blue'
    create :id => 3, :name => 'green'
  end

Customized enumeration

  class Book < ActiveRecord::Base
    acts_as_enumeration :title

    create :id => 1, :title => 'Blink'
  end

Additional enumeration attributes

  class Book < ActiveRecord::Base
    acts_as_enumeration :title

    column :author, :string
    column :num_pages, :integer

    validates_presence_of :author
    validates_presence_of :num_pages

    create :id => 1, :title => 'Blink', :author => 'Malcolm Gladwell', :num_pages => 277
  end

Associations

  class ColorGroup < ActiveRecord::Base
    acts_as_enumeration

    has_many :colors, :foreign_key => 'group_id'

    create :id => 1, :name => 'RGB'
    create :id => 2, :name => 'CMYK'
  end

  class Color < ActiveRecord::Base
    acts_as_enumeration

    column :group_id, :integer

    belongs_to :group, :class_name => 'ColorGroup'
    has_many :cars
  end

  class Car < ActiveRecord::Base
    belongs_to :color
  end

Setting enumeration attributes

  class Color < ActiveRecord::Base
    acts_as_enumeration

    create :id => 1, :name => 'red'
    create :id => 2, :name => 'blue'
    create :id => 3, :name => 'green'
  end

  class Car < ActiveRecord::Base
    belongs_to :car
  end

  car = Car.create(:color => 'red')
  car.color = 'blue'

Camelcase/underscore lookups

If you want to look up enumeration records by the underscore equivalent of its camelcased name, the following technique should be used:

  class CreditCardType < ActiveRecord::Base
    acts_as_enumeration

    column :display_name

    def initialize(attributes = nil) #:nodoc:
      super
      self.name = default_name unless attributes && attributes.include?(:name)
    end

    private
      def default_name
        display_name.gsub(/[^A-Za-z0-9-]/, '').underscore
      end

    create :id => 1, :display_name => 'Visa'
    create :id => 2, :display_name => 'Mastercard'
    create :id => 3, :display_name => 'American Express', :name => 'amex'
    create :id => 4, :display_name => 'Discover'
  end

Rather than relying on the plugin to do the conversion, this technique gives you more control over the exact values that can be used for looking up enumerations. Note that this could be simplified even further using the active_record_defaults plugin.

Future development

See the in_memory branch for for an experimental re-implementation of this plugin. That branch uses an in-memory SQLite3 database for managing enumerations and helps ease maintenance of the implementation, while allow the full utilization of ActiveRecord.

Testing

Before you can run any tests, the following gem must be installed:

To run against a specific version of Rails:

  rake test RAILS_FRAMEWORK_ROOT=/path/to/rails

Dependencies

  • Rails 2.1 or later

References