diff --git a/lib/micromachine.rb b/lib/micromachine.rb index bc09755..72f475c 100644 --- a/lib/micromachine.rb +++ b/lib/micromachine.rb @@ -3,9 +3,11 @@ class MicroMachine InvalidState = Class.new(ArgumentError) attr_reader :transitions_for + attr_reader :previous_state attr_reader :state def initialize(initial_state) + @previous_state = nil @state = initial_state @transitions_for = Hash.new @callbacks = Hash.new { |hash, key| hash[key] = [] } @@ -20,7 +22,7 @@ def when(event, transitions) end def trigger(event) - trigger?(event) and change(event) + trigger?(event) and change(event) and notify(event) end def trigger!(event) @@ -42,9 +44,13 @@ def states end private - def change(event) + @previous_state = @state @state = transitions_for[event][@state] + true + end + + def notify(event) callbacks = @callbacks[@state] + @callbacks[:any] callbacks.each { |callback| callback.call(event) } true diff --git a/test/transitions.rb b/test/transitions.rb index b131972..b99cd1e 100644 --- a/test/transitions.rb +++ b/test/transitions.rb @@ -12,6 +12,7 @@ test "defines initial state" do |machine| assert_equal :pending, machine.state + assert_equal nil, machine.previous_state end test "raises an error if an invalid event is triggered" do |machine| @@ -24,26 +25,32 @@ assert !machine.trigger?(:reset) assert !machine.trigger(:reset) assert_equal :pending, machine.state + assert_equal nil, machine.previous_state end test "changes the state if transition is possible" do |machine| assert machine.trigger?(:confirm) assert machine.trigger(:confirm) assert_equal :confirmed, machine.state + assert_equal :pending, machine.previous_state end test "discerns multiple transitions" do |machine| machine.trigger(:confirm) assert_equal :confirmed, machine.state + assert_equal :pending, machine.previous_state machine.trigger(:reset) assert_equal :pending, machine.state + assert_equal :confirmed, machine.previous_state machine.trigger(:ignore) assert_equal :ignored, machine.state + assert_equal :pending, machine.previous_state machine.trigger(:reset) assert_equal :pending, machine.state + assert_equal :ignored, machine.previous_state end test "raises an error if event is triggered from/to a non complatible state" do |machine|