state_machine
Initializations
- Initial values for state machine attributes are automatically assigned when a new object is created
- This will not work if the class defines an
initialize
method without callingsuper
Examples
class Vehicle
state_machine :state, :initial => :parked do
...
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
vehicle.state # => "parked"
In the above example, no initialize
method is defined. As a result,
the default behavior of initializing the state machine attributes is used.
In the following example, a custom initialize
method is defined:
class Vehicle
state_machine :state, :initial => :parked do
...
end
def initialize
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7c77678>
vehicle.state # => nil
Since the initialize
method is defined, the state machine attributes
never get initialized. In order to ensure that all initialization hooks
are called, the custom method must call super
without any arguments
like so:
class Vehicle
state_machine :state, :initial => :parked do
...
end
def initialize(attributes = {})
...
super()
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
vehicle.state # => "parked"
Because of the way the inclusion of modules works in Ruby, calling
super()
will not only call the superclass's initialize
, but
also initialize
on all included modules. This allows the original state
machine hook to get called properly.
If you want to avoid calling the superclass's constructor, but still want to initialize the state machine attributes:
class Vehicle
state_machine :state, :initial => :parked do
...
end
def initialize(attributes = {})
...
initialize_state_machines
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
vehicle.state # => "parked"
You may also need to call the initialize_state_machines
helper manually
in cases where you want to change how static / dynamic initial states get
set. For example, the following example forces the initialization of
static states regardless of their current value:
class Vehicle
state_machine :state, :initial => :parked do
state nil, :idling
...
end
def initialize(attributes = {})
@state = 'idling'
initialize_state_machines(:static => :force) do
...
end
end
end
vehicle = Vehicle.new # => #<Vehicle:0xb7c8dbf8 @state="parked">
vehicle.state # => "parked"
The above example is also noteworthy because it demonstrates how to avoid
initialization issues when nil
is a valid state. Without passing in
:static => :force
, state_machine would never have initialized
the state because nil
(the default attribute value) would have been
interpreted as a valid current state. As a result, state_machine would
have simply skipped initialization.