Implement state patterns for your enumerated_attributes
Install
-
sudo gem enumerated_state
Use
-
require ‘enumerated_state’
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.
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
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
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'
-
meta_programming
-
mixology
-
enumerated_attribute