Skip to content

Commit

Permalink
Added tests for calling the failure and success callbacks
Browse files Browse the repository at this point in the history
This uncovered some bug not firering the event_failed callback
in any case of an exception has been raised. This is now handled.

The exception is just re-raised if the record doesn't have defined
a event_failed callback. If he had it is up to the implementation
to handle the execption. We are just return false.
  • Loading branch information
code-later committed Nov 23, 2011
1 parent 9bc17b1 commit e0b886b
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 12 deletions.
30 changes: 18 additions & 12 deletions lib/transitions/machine.rb
Expand Up @@ -45,22 +45,28 @@ def update(options = {}, &block)

def fire_event(event, record, persist, *args)
state_index[record.current_state(@name)].call_action(:exit, record)
if new_state = @events[event].fire(record, nil, *args)
state_index[new_state].call_action(:enter, record)

if record.respond_to?(event_fired_callback)
record.send(event_fired_callback, record.current_state, new_state, event)
begin
if new_state = @events[event].fire(record, nil, *args)
state_index[new_state].call_action(:enter, record)

if record.respond_to?(event_fired_callback)
record.send(event_fired_callback, record.current_state, new_state, event)
end

record.current_state(@name, new_state, persist)
@events[event].success.call(record) if @events[event].success
return true
else
record.send(event_fired_callback, event) if record.respond_to?(event_failed_callback)
return false
end

record.current_state(@name, new_state, persist);
@events[event].success.call(record) if @events[event].success
true
else
rescue => e
if record.respond_to?(event_failed_callback)
record.send(event_failed_callback, event)
return false
else
raise e
end

false
end
end

Expand Down
60 changes: 60 additions & 0 deletions test/test_state_transition_success_callback.rb
@@ -0,0 +1,60 @@
require 'helper'

class DrivingInstructor
def self.applause!
end
end

class DrivingSchoolCar
include Transitions

state_machine do
state :parked
state :running
state :driving
state :switched_off

event :start_driving, :success => lambda { |car| DrivingInstructor.applause! } do
transitions :from => :parked, :to => :driving, :on_transition => [:start_engine, :loosen_handbrake, :push_gas_pedal]
end

event :switch_off_engine do
transitions :from => :parked, :to => :switched_off
end
end

%w!start_engine loosen_handbrake push_gas_pedal!.each do |m|
define_method(m){}
end
end

class TestStateTransitionSuccessCallback < Test::Unit::TestCase
def setup
@car = DrivingSchoolCar.new
end

test "should execute the success callback after successfull event execution" do
DrivingInstructor.expects(:applause!)

@car.start_driving!
end

test "should not execute the success callback after event execution failed" do
DrivingInstructor.expects(:applause!).never

@car.stubs(:event_failed)
@car.expects(:loosen_handbrake).raises("Drive with handbrake fail!")
@car.start_driving!
end

test "should execute the event_failed_callback and don't raise error if callback is defined" do
@car.start_driving
@car.expects(:event_failed).with(:switch_off_engine)
@car.switch_off_engine
end

test "should just re-raise any error on transition if the event_failed_callback isn't defined" do
@car.start_driving
assert_raise(Transitions::InvalidTransition) { @car.switch_off_engine }
end
end

0 comments on commit e0b886b

Please sign in to comment.