ar-enums
This is a simple solution for defining enumerations in your Rails models.
Description
It provides two forms of enumerations:
-
Internal, i.e. defined within the owner of the enum, for the simple cases.
-
External, i.e. defined on it’s own class, for the complex ones.
In both cases the enum values are stored in-memory. Let’s see some examples of both kinds.
Internal enumerations
Can be defined in three flavours:
Array of values style
This is the simplest and probably the most frecuent case:
class TrafficLight < ActiveRecord::Base
enum :state, %w[red green yellow]
end
tl = TrafficLight.new(:state => :green)
tl.state # => #<TrafficLight::State @name="green", @id=2>
tl.state_id # => 2
tl.state.green? # => true
As you can see each enum value is an instance of a dinamically generated class (which inherits from ActiveRecord::Enum) and has an ordinal value, id, autogenerated staring on 1.
The enumerations array is accessed with a class method:
TrafficLight.states # => [#<TrafficLight::State @name="red", @id=1>, #<TrafficLight::State @name="green", @id=2>, ...]
By default when #to_s
is called on a Enum instance it returns the name titleized, but this behaviour can be overrided. See Displaying Enums section below.
Array of hashes style
This allows you to define new columns in the Enum value. If the :id is not specified is generated for you.
class TrafficLight < ActiveRecord::Base
enum :state, [
{ :name => :red, :stop_traffic => true, :rgb => 0xF00 },
{ :name => :green, :stop_traffic => false, :rgb => 0x0F0 }
]
end
tl = TrafficLight.new(:state => :green)
tl.state_id # => 2
tl.state.stop_traffic # => false
tl.state.rgb # => 0x0F0
Block style
class TrafficLight < ActiveRecord::Base
enum :state do
red :stop_traffic => true, :rgb => 0xF00
green :stop_traffic => false, :rgb => 0x0F0
end
end
External enumerations
When you have shared enumerations or just don’t want to clutter the owner model with enums definitions, the enumeration can be on it’s own class, as the State enum in the following example:
class TrafficLight < ActiveRecord::Base
enum :state
end
class State < ActiveRecord::Enum
enumeration do
red :stop_traffic => true, :rgb => 0xF00, :desc => 'Rojo'
green :stop_traffic => false, :rgb => 0x0F0, :desc => 'Verde'
end
end
State[:red] # => #<State @name="red", @id=1, ...>
State[:red].to_s # => "Rojo"
Note the block style sintax is exactly the same as in the internal enumerations. In fact any of the 3 styles mencioned above can be used on external enumerations.
Also note the #to_s
by default return the value of the :desc
column. Of course you can override the #to_s
method as usual.
Then you can access the enumerations collection from both places:
TrafficLight.states # => [#<State @name="red", @id=1, ...>, #<State @name="green", @id=2, ...>]
States.all # => [#<State @name="red", @id=1, ...>, #<State @name="green", @id=2, ...>]
The enum
method accept a :class_method
option similar to the one in belongs_to
and others to specify the class of the enum.
Displaying Enums
In the array of values style the default is the name titleized but you can pass a :label
options to override:
class TrafficLight < ActiveRecord::Base
enum :state, %w[red green yellow], :label => :upcase
end
TrafficLight.states.map(&:to_s) # => ["RED", "GREEN", "YELLOW"]
If you use the block o array of hashes sintax and add a :desc
column it will be used as #to_s
, unless a :label
option is passed.
TODO
-
Remove the dependency with ActiveRecord so it can be used outside Rails.
-
Allow to store enums in the database.
Note on Patches/Pull Requests
-
Fork the project.
-
Make your feature addition or bug fix.
-
Add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-
Send me a pull request. Bonus points for topic branches.
Copyright
Copyright © 2010 Emmanuel Nicolau. See LICENSE for details.