Permalink
Browse files

Add PluginAWeek::StateMachine::Machine#states

Add PluginAWeek::StateMachine::Event#transitions
  • Loading branch information...
1 parent b90d731 commit 26d60afa4705981762799dfc36d46794b2bff370 @obrie obrie committed Jul 3, 2008
Showing with 50 additions and 2 deletions.
  1. +2 −0 CHANGELOG.rdoc
  2. +5 −0 lib/state_machine/event.rb
  3. +10 −0 lib/state_machine/machine.rb
  4. +9 −0 test/unit/event_test.rb
  5. +24 −2 test/unit/machine_test.rb
View
@@ -1,5 +1,7 @@
== master
+* Add PluginAWeek::StateMachine::Machine#states
+* Add PluginAWeek::StateMachine::Event#transitions
* Allow creating transitions with no from state (effectively allowing the transition for *any* from state)
* Reduce the number of objects created for each transition
@@ -11,6 +11,9 @@ class Event
# The name of the action that fires the event
attr_reader :name
+ # The list of transitions that can be made for this event
+ attr_reader :transitions
+
delegate :owner_class,
:to => :machine
@@ -21,6 +24,7 @@ def initialize(machine, name, options = {})
@machine = machine
@name = name
@options = options.stringify_keys
+ @transitions = []
add_transition_actions
add_transition_callbacks
@@ -63,6 +67,7 @@ def transition(options = {})
callback = Proc.new {|record, *args| try_transition(transition, true, record, *args)}
owner_class.send("transition_bang_on_#{name}", callback, options)
+ transitions << transition
transition
end
@@ -15,6 +15,9 @@ class Machine
# The events that trigger transitions
attr_reader :events
+ # A list of the states defined in the transitions of all of the events
+ attr_reader :states
+
# The attribute for which the state machine is being defined
attr_accessor :attribute
@@ -44,6 +47,7 @@ def initialize(owner_class, attribute, options = {})
@attribute = attribute.to_s
@initial_state = options[:initial]
@events = {}
+ @states = []
add_named_scopes
end
@@ -110,6 +114,12 @@ def event(name, options = {}, &block)
name = name.to_s
event = events[name] = Event.new(self, name, options)
event.instance_eval(&block)
+
+ # Record the states
+ event.transitions.each do |transition|
+ @states |= ([transition.to_state] + transition.from_states)
+ end
+
event
end
View
@@ -14,6 +14,10 @@ def test_should_have_a_name
assert_equal 'turn_on', @event.name
end
+ def test_should_not_have_any_transitions
+ assert @event.transitions.empty?
+ end
+
def test_should_define_an_event_action_on_the_owner_class
switch = new_switch
assert switch.respond_to?(:turn_on)
@@ -81,6 +85,11 @@ def test_should_allow_transitioning_from_multiple_states
assert @event.transition(:to => 'on', :from => %w(off on))
end
+ def test_should_have_transitions
+ @event.transition(:to => 'on')
+ assert @event.transitions.any?
+ end
+
def teardown
Switch.class_eval do
@transition_on_turn_on_callbacks = nil
View
@@ -20,6 +20,10 @@ def test_should_have_an_owner_class
def test_should_not_have_any_events
assert @machine.events.empty?
end
+
+ def test_should_not_have_any_states
+ assert @machine.states.empty?
+ end
end
class MachineWithInvalidOptionsTest < Test::Unit::TestCase
@@ -121,9 +125,27 @@ def test_should_evaluate_block_within_event_context
assert responded
end
- def test_should_store_the_event
+ def test_should_have_events
@machine.event(:turn_on) {}
- assert_equal 1, @machine.events.size
+ assert_equal %w(turn_on), @machine.events.keys
+ end
+end
+
+class MachineWithEventsAndTransitionsTest < Test::Unit::TestCase
+ def setup
+ @machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
+ @machine.event(:turn_on) do
+ transition :to => 'on', :from => 'off'
+ transition :to => 'error', :from => 'unknown'
+ end
+ end
+
+ def test_should_have_events
+ assert_equal %w(turn_on), @machine.events.keys
+ end
+
+ def test_should_have_states
+ assert_equal %w(on off error unknown), @machine.states
end
end

0 comments on commit 26d60af

Please sign in to comment.