1
0
Fork 0
mirror of https://github.com/aasm/aasm synced 2023-03-27 23:22:41 -04:00

Allow multiple transitions in a single event with the same to and from states

As reported in https://github.com/aasm/aasm/issues/372 and https://github.com/aasm/aasm/issues/362,
if two transitions in the same event have the same `to` and `from` states but differ in their
guards, if any transition is valid, the first transition is the one that's always executed.
This attempts to resolve that issue.
This commit is contained in:
Dathan Bennett 2016-10-12 13:21:11 -07:00
parent 66d2a0de81
commit 6a924d6b1f
3 changed files with 44 additions and 3 deletions

View file

@ -128,12 +128,13 @@ module AASM::Core
transitions.each do |transition|
next if to_state and !Array(transition.to).include?(to_state)
if (options.key?(:may_fire) && Array(transition.to).include?(options[:may_fire])) ||
if (options.key?(:may_fire) && transition.eql?(options[:may_fire])) ||
(!options.key?(:may_fire) && transition.allowed?(obj, *args))
result = to_state || Array(transition.to).first
if options[:test_only]
# result = true
result = transition
else
result = to_state || Array(transition.to).first
Array(transition.to).each {|to| @valid_transitions[to] = transition }
transition.execute(obj, *args)
end

View file

@ -0,0 +1,31 @@
class MultipleTransitionsThatDifferOnlyByGuard
include AASM
attr_accessor :executed_correctly
aasm do
state :start, :initial => true
state :gone
event :go do
transitions :from => :start, :to => :gone, :guard => :returns_false, :after => :this_should_not_execute
transitions :from => :start, :to => :gone, :guard => :returns_true, :after => :this_should_execute
end
end
def returns_false
false
end
def returns_true
true
end
def this_should_not_execute
raise RuntimeError, "This should not execute"
end
def this_should_execute
self.executed_correctly = true
end
end

View file

@ -0,0 +1,9 @@
require 'spec_helper'
describe "multiple transitions that differ only by guard" do
let(:job) { MultipleTransitionsThatDifferOnlyByGuard.new }
it 'does not follow the first transition if its guard fails' do
expect{job.go}.not_to raise_error
end
end