AlterEgo is a Ruby implementation of the State pattern as described by the Gang of Four. It differs from other Ruby state machine libraries in that it focuses on providing polymorphic behavior based on object state. In effect, it makes it easy to give an object different “personalities” depending on the state it is in.
sudo gem install alter-ego
Sometimes you want a single object to behave differently depending on what state it’s in. For instance, a traffic light has a different color depending on whether it is informing people that they should stop, slow down, or proceed. Or a user account object might behave differently depending on whether the account is in the “confirmed” state. AlterEgo can help you set up these state-based object “personalities”.
AlterEgo will help you to define a set of valid states for your objects, and to define the allowable transitions between states. The real strength of AlterEgo, however, is in defining separate behaviors for each state that the object is in. Underneath the covers, AlterEgo will arrange for your object to delegate to a different state object depending on what state it is in. You can either explicitly define these state objects as classes, or use a concise DSL provided by AlterEgo.
class TrafficLight include AlterEgo state :proceed, :default => true do handle :color do "green" end transition :to => :caution, :on => :cycle! end state :caution do handle :color do "yellow" end transition :to => :stop, :on => :cycle! end state :stop do handle :color do "red" end transition :to => :proceed, :on => :cycle! end end light = TrafficLight.new light.color # => "green" light.cycle! light.color # => "yellow" light.cycle! light.color # => "red" light.cycle! light.color # => "green"
- Implemented as a module which can be included in any Ruby class.
- Fully tested with literate RSpec
- Guard clauses may be defined for each transition.
- Enter/exit actions may be defined for each state.
- For more advanced scenarios, arbitrary “request filters” may be defined with full control over which requests are filtered.
- Uses dynamic module generation and delegation instead of method rewriting.
- Pervasive contract-checking catches mistakes in library usage early.
- Storing and reading current state is completely customizable, making it easier to add AlterEgo to legacy classes.
See the project’s RDoc
You can fetch the source from RubyForge using Git:
git clone git://rubyforge.org/alter-ego.git
Thank you to MDlogix, where this code was initially developed, for kindly permitting me to release AlterEgo to the public.
This code is free to use under the terms of the MIT license.
Questions, comments, suggestions: Email Avdi Grimm