Define enum classes in Rails and use them to enumerate ActiveRecord attributes. Brings together some ideas of similar plugins that I liked and does it they way I prefer.
Enum values are stored in memory at the moment but I plan to add database and possibly others.
From version 0.7 onwards this plugin will only have Rails 3 support. If you need Rails 2 compatibility, check the 0.6 branch.
geminstallactive_enum
Put this in your Gemfile
gem'active_enum'
Then generate the config initializer file
railsgenerateactive_enum:install
Define an enum class with values
classSex<ActiveEnum::Basevalue:id=>1, :name=>'Male'value:id=>2, :name=>'Female'end
Define with id as the key
classSex<ActiveEnum::Basevalue1=>'Male'value2=>'Female'end
Define using implicit id values
classSex<ActiveEnum::Basevalue:name=>'Male'value:name=>'Female'end
Beware that if you change the order of values defined in an enum which don’t have explicit ids, then the ids will change. This could corrupt your data if the enum values have been stored in a model record, as they will no longer map to the original enum.
Define values with meta data
classSex<ActiveEnum::Basevalue:id=>1, :name=>'Male', :symbol=>'♂'value:id=>2, :name=>'Female', :symbol=>'♀'end
The meta data can be any other key-value pairs, it’s not limited to certain keys.
Enum class usage
Sex[1] # => 'Male'Sex['Male'] # => 1Sex[:male] # => 1Sex.meta(1) # => { :symbol => '♂' }Sex.to_select# => [['Male', 1], ['Female',2]] for select form helpers
To define the sorting of returned values use the order method. Which is useful for to_select method.
classSex<ActiveEnum::Baseorder:ascvalue:id=>1, :name=>'Male'value:id=>2, :name=>'Female'end
By default the order is ascending (:asc) but you can also choose descending (:desc) or in order of definition (:as_defined). The last option is useful when supplying id values but have a specific order needed to display them.
Use the enum to enumerate an ActiveRecord model attribute
classUser<ActiveRecord::Baseenumerate:sex, :with=>Sexend
Skip the with option if the enum can be implied from the attribute
classUser<ActiveRecord::Baseenumerate:sexend
Define enum class implicitly from enumerate block. Enum class is namespaced by model class.
classUser<ActiveRecord::Base# defines User::Sex enum classenumerate:sexdovalue:name=>'Male'endend
Multiple attributes with same enum
classPatient<ActiveRecord::Baseenumerate:to, :from, :with=>Sexend
Access the enum values and the enum class using the attribute method with a symbol for the enum component you want
user = User.newuser.sex = 1user.sex# => 1user.sex(:id) # => 1user.sex(:name) # => 'Male'user.sex(:enum) # => Sexuser.sex(:symbol) # => ♂. Can use any meta data key.
You can set the default to return the enum name value for enumerated attribute
ActiveEnum.use_name_as_value = trueuser.sex# => 'Male'
You can check if the attribute value matches a particular enum value by passing the enum value as an argument to the question method
user.sex?(:male) # => trueuser.sex?(:Male) # => trueuser.sex?('Male') # => trueuser.sex?('Female') # => false
A convenience method on the class is available to the enum class of any enumerated attribute
User.active_enum_for(:sex) # => Sex
Define enum classes in bulk without class files, in an initializer file for example.
ActiveEnum.definedo# defines Sexenum(:sex) dovalue:name=>'Male'value:name=>'Female'end# defines Languageenum(:language) dovalue:name=>'English'value:name=>'German'endend
All defined enum classes are stored in ActiveEnum.enum_classes array if you need look them up or iterate over them.
You can make an existing model class behave like an enum class with acts_as_enum
classCountry<ActiveRecord::Baseacts_as_enum:name_column=>'short_name'end
Giving you the familiar enum methods
Country[1] Country['Australia'] Country.to_select
There is support for Formtastic and SimpleForm to make it easier to use the enum values as select options. The plugins have an almost identical API which is handy. You just need to require the extension for the respective plugin in an initialiser:
Formtastic:
require'active_enum/form_helpers/formtastic'
Or, SimpleForm:
require'active_enum/form_helpers/simple_form'
The input type will be automatically detected for enumerated attributes. You can override with the :as option as normal.
The to_select method looks up translations for the enum values in active_enum. The translation key is built from the enum class name and the enum value’s name attribute downcased and underscored.
For example:
active_enum: sex: male: мужчина female: женский
If a translation cannot be found, the enum’s name attribute is used instead.
If the enum class is namespaced, e.g. User::Sex, then the translation key is also scoped in the namespace:
active_enum: user: sex: male: мужчина female: женский
The enum class also includes translate method (also aliased as t) for translating the enum values. The translation can be looked up by either id or name.
Sex.translate(:male) # => 'мужчина'Sex.t(:male) # => 'мужчина'
The ActiveRecord attribute method can be used to look up the translated value:
user.sex(:translation) # => 'мужчина'
storage options of memory, database or yaml
use custom method name for the enumerated attribute
Copyright © 2009 Adam Meehan, released under the MIT license