Skip to content
Browse files

Add other_states directive for defining additional states not referen…

…ced in transitions or callbacks
  • Loading branch information...
1 parent 0da590e commit 2269c93de1fd38c7d581136af17ecf6a1cfaf89f Pete Forde committed with obrie Dec 7, 2008
Showing with 49 additions and 1 deletion.
  1. +1 −0 CHANGELOG.rdoc
  2. +36 −1 lib/state_machine/machine.rb
  3. +12 −0 test/unit/machine_test.rb
View
1 CHANGELOG.rdoc
@@ -1,5 +1,6 @@
== master
+* Add other_states directive for defining additional states not referenced in transitions or callbacks [Pete Forde]
* Add next_#{event}_transition for getting the next transition that would be performed if the event were invoked
* Add the ability to override the pluralized name of an attribute for creating scopes
* Add the ability to halt callback chains by: throw :halt
View
37 lib/state_machine/machine.rb
@@ -196,6 +196,7 @@ def initialize(owner_class, *args)
# Set machine configuration
@attribute = (args.first || 'state').to_s
@events = {}
+ @other_states = []
@callbacks = {:before => [], :after => []}
@action = options[:action]
@@ -308,13 +309,47 @@ def initial_state(object)
def states
@states ||=
begin
- states = []
+ states = @other_states.dup
events.values.each {|event| states.concat(event.known_states)}
callbacks.values.flatten.each {|callback| states.concat(callback.guard.known_states)}
states
end.uniq
end
+ # Defines additional states that are possible in the state machine, but
+ # which are derived outside of any events/transitions or possibly
+ # dynamically via Proc. This allows the creation of state conditionals
+ # which are not defined in the standard :to or :from structure.
+ #
+ # == Example
+ #
+ # class Vehicle
+ # state_machine :initial => 'parked' do
+ # event :ignite do
+ # transition :to => 'idling', :from => 'parked'
+ # end
+ #
+ # other_states %w(stalled stopped)
+ # end
+ #
+ # def stop
+ # self.state = 'stopped'
+ # end
+ # end
+ #
+ # In the above state machine, the known states would be:
+ # * +idling+
+ # * +parked+
+ # * +stalled+
+ # * +stopped+
+ #
+ # Since +stalled+ and +stopped+ are not referenced in any transitions or
+ # callbacks, they are explicitly defined.
+ def other_states(*args)
+ @states = nil # Reset the cache
+ @other_states |= args
+ end
+
# Defines an event for the machine.
#
# == Instance methods
View
12 test/unit/machine_test.rb
@@ -793,6 +793,18 @@ def test_should_not_duplicate_states_defined_in_multiple_event_transitions
end
end
+class MachineWithOtherStates < Test::Unit::TestCase
+ def setup
+ @klass = Class.new
+ @machine = PluginAWeek::StateMachine::Machine.new(@klass)
+ @machine.other_states('on', 'off')
+ end
+
+ def test_should_include_other_states_in_known_states
+ assert_equal %w(off on), @machine.states.sort
+ end
+end
+
class MachineWithOwnerSubclassTest < Test::Unit::TestCase
def setup
@klass = Class.new

0 comments on commit 2269c93

Please sign in to comment.
Something went wrong with that request. Please try again.