enumerated_state
Implement state patterns for your enumerated_attributes
Resources
Install
-
sudo gem enumerated_state
Use
-
require ‘enumerated_state’
Description
This gem belongs to the ASPIUM family of gems – (Another State Pattern Implemented Using Mixology). This ASPIUM adds state pattern support to enumerated attributes (see enumerated_attribute) and allows multiple state variables per object, one for each enumerated attribute.
Usage
Basic implementation
If you are using enumerated_attribute, you may have code looking something like
class Tractor
def direction
case
when tractor.gear_is_first? then 'forwards'
when tractor.gear_is_reverse? then 'backwards'
else
'stopped'
end
end
end
We can clean this up a little by using acts_as_enumerated_state like this
class Tractor
enum_attr :gear, %w(reverse ^neutral first)
acts_as_enumerated_state :gear
def direction; nil; end # called if gear == nil
module Reverse
def direction; 'backwards'; end
end
module Neutral
def direction; 'stopped'; end
end
module First
def direction; 'forwards'; end
end
end
Multi-variable state and enum value conflicts
If your attributes share some enum values with the same name, there will be confusion as to which module belongs to which enumeration. You can clear up the collision by using the :module option like this
class Foobar
enum_attr :alpha, %w(state1 state2)
enum_attr :beta, %w(state1 state2 state3) # names will collide when mapped to modules
acts_as_enumerated_state :alpha
acts_as_enumerated_state :beta, :module=>'Beta'
module State1 ... end
module State2 ... end
module Beta
module State1 ... end
module State2 ... end
module State3 ... end
end
end
Strict versus non-strict
By default, acts_as_enumerated_state assigns one module for each enumeration and fails when it cannot find the module. For example, the following code causes an error
class Tractor
enum_attr :gear, %w(reverse neutral first)
acts_as_enumerated_state :gear
module Reverse ... end
# where's the module for :neutral?
module First ... end
end
Tractor.new.gear = :neutral #error because there's no module
But sometimes you may not need a module for each enumeration. You may want some enumerations to use a method defined by the object itself. You can back off the strictness by setting the :strict option to false like this
class Tractor
enum_attr :gear, %w(reverse neutral first)
acts_as_enumerated_state :gear, :strict=>false
def motion; 'stopped'; end
module Reverse
def motion; 'backwards'; end
end
# no neutral module needed
module First
def motion; 'forwards'; end
end
end
t = Tractor.new
t.gear = :neutral
t.motion # calls motion on the object and returns 'stopped'
Dependencies
-
meta_programming
-
mixology
-
enumerated_attribute