mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Fixes incorrect permitted states
Permitted states now returns the correct states when an event has more than one transition, and if a transition uses a guard.
This commit is contained in:
parent
bdf7e4c97b
commit
2449fcc165
3 changed files with 56 additions and 5 deletions
|
@ -35,11 +35,23 @@ module AASM
|
|||
|
||||
def states(options={})
|
||||
if options[:permitted]
|
||||
# ugliness level 1000
|
||||
permitted_event_names = events(:permitted => true).map(&:name)
|
||||
transitions = @instance.class.aasm(@name).state_machine.events.values_at(*permitted_event_names).compact.map {|e| e.transitions_from_state(current_state) }
|
||||
tos = transitions.map {|t| t[0] ? t[0].to : nil}.flatten.compact.map(&:to_sym).uniq
|
||||
@instance.class.aasm(@name).states.select {|s| tos.include?(s.name.to_sym)}
|
||||
permitted_events = events(:permitted => true)
|
||||
|
||||
# An array of arrays. Each inner array represents the transitions that
|
||||
# transition from the current state for an event
|
||||
event_transitions = permitted_events.map {|e| e.transitions_from_state(current_state) }
|
||||
|
||||
# An array of symbols that are possible :to transition states
|
||||
to_state_names = event_transitions.map do |transitions|
|
||||
return nil if transitions.empty?
|
||||
|
||||
# Return the :to state of the first transition that is allowed or nil
|
||||
transition = transitions.find { |t| t.allowed?(@instance) }
|
||||
transition ? transition.to : nil
|
||||
end.flatten.compact.uniq
|
||||
|
||||
# Select states that are in to_state_names
|
||||
@instance.class.aasm(@name).states.select {|s| to_state_names.include?(s.name)}
|
||||
else
|
||||
@instance.class.aasm(@name).states
|
||||
end
|
||||
|
|
24
spec/models/multi_transitioner.rb
Normal file
24
spec/models/multi_transitioner.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
class MultiTransitioner
|
||||
include AASM
|
||||
|
||||
attr_accessor :can_run
|
||||
|
||||
def initialize
|
||||
@can_run = false
|
||||
end
|
||||
|
||||
aasm do
|
||||
state :sleeping, :initial => true
|
||||
state :running
|
||||
state :dancing
|
||||
|
||||
event :start do
|
||||
transitions :from => :sleeping, :to => :running, guard: :runnable?
|
||||
transitions :from => :sleeping, :to => :dancing
|
||||
end
|
||||
end
|
||||
|
||||
def runnable?
|
||||
@can_run
|
||||
end
|
||||
end
|
|
@ -17,6 +17,7 @@ describe 'inspection for common cases' do
|
|||
context "instance level inspection" do
|
||||
let(:foo) { Foo.new }
|
||||
let(:two) { FooTwo.new }
|
||||
let(:multi) { MultiTransitioner.new }
|
||||
|
||||
it "delivers all states" do
|
||||
states = foo.aasm.states
|
||||
|
@ -37,11 +38,13 @@ describe 'inspection for common cases' do
|
|||
states = two.aasm.states
|
||||
expect(states).to include(:open)
|
||||
expect(states).to include(:closed)
|
||||
expect(states).to include(:final)
|
||||
expect(states).to include(:foo)
|
||||
|
||||
states = two.aasm.states(:permitted => true)
|
||||
expect(states).to include(:closed)
|
||||
expect(states).not_to include(:open)
|
||||
expect(states).not_to include(:final)
|
||||
|
||||
two.close
|
||||
expect(two.aasm.states(:permitted => true)).to be_empty
|
||||
|
@ -54,6 +57,18 @@ describe 'inspection for common cases' do
|
|||
foo.close
|
||||
expect(foo.aasm.events).to be_empty
|
||||
end
|
||||
|
||||
it "delivers permitted states when multiple transitions are defined" do
|
||||
multi.can_run = false
|
||||
states = multi.aasm.states(:permitted => true)
|
||||
expect(states).to_not include(:running)
|
||||
expect(states).to include(:dancing)
|
||||
|
||||
multi.can_run = true
|
||||
states = multi.aasm.states(:permitted => true)
|
||||
expect(states).to include(:running)
|
||||
expect(states).to_not include(:dancing)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should list states in the order they have been defined' do
|
||||
|
|
Loading…
Add table
Reference in a new issue