mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Add ability to set up transitions without specifying from - these will allow transitioning from ANY state
This commit is contained in:
parent
6357675b6b
commit
afa65d8603
3 changed files with 42 additions and 25 deletions
|
@ -13,34 +13,11 @@ module AASM
|
||||||
# executes the transition guards to determine if a transition is even
|
# executes the transition guards to determine if a transition is even
|
||||||
# an option given current conditions.
|
# an option given current conditions.
|
||||||
def may_fire?(obj, to_state=nil, *args)
|
def may_fire?(obj, to_state=nil, *args)
|
||||||
transitions = @transitions.select { |t| t.from == obj.aasm_current_state }
|
_fire(obj, true, to_state, *args) # true indicates test firing
|
||||||
return false if transitions.size == 0
|
|
||||||
|
|
||||||
result = false
|
|
||||||
transitions.each do |transition|
|
|
||||||
next if to_state and !Array(transition.to).include?(to_state)
|
|
||||||
if transition.perform(obj, *args)
|
|
||||||
result = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def fire(obj, to_state=nil, *args)
|
def fire(obj, to_state=nil, *args)
|
||||||
transitions = @transitions.select { |t| t.from == obj.aasm_current_state }
|
_fire(obj, false, to_state, *args) # false indicates this is not a test (fire!)
|
||||||
return nil if transitions.size == 0
|
|
||||||
|
|
||||||
next_state = nil
|
|
||||||
transitions.each do |transition|
|
|
||||||
next if to_state and !Array(transition.to).include?(to_state)
|
|
||||||
if transition.perform(obj, *args)
|
|
||||||
next_state = to_state || Array(transition.to).first
|
|
||||||
transition.execute(obj, *args)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
next_state
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def transitions_from_state?(state)
|
def transitions_from_state?(state)
|
||||||
|
@ -112,6 +89,32 @@ module AASM
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Execute if test? == false, otherwise return true/false depending on whether it would fire
|
||||||
|
def _fire(obj, test, to_state=nil, *args)
|
||||||
|
if @transitions.map(&:from).any?
|
||||||
|
transitions = @transitions.select { |t| t.from == obj.aasm_current_state }
|
||||||
|
return nil if transitions.size == 0
|
||||||
|
else
|
||||||
|
transitions = @transitions
|
||||||
|
end
|
||||||
|
|
||||||
|
result = test ? false : nil
|
||||||
|
transitions.each do |transition|
|
||||||
|
next if to_state and !Array(transition.to).include?(to_state)
|
||||||
|
if transition.perform(obj, *args)
|
||||||
|
if test
|
||||||
|
result = true
|
||||||
|
else
|
||||||
|
result = to_state || Array(transition.to).first
|
||||||
|
transition.execute(obj, *args)
|
||||||
|
end
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
def _fire_callbacks(action, record)
|
def _fire_callbacks(action, record)
|
||||||
case action
|
case action
|
||||||
when Symbol, String
|
when Symbol, String
|
||||||
|
@ -122,9 +125,12 @@ module AASM
|
||||||
end
|
end
|
||||||
|
|
||||||
def transitions(trans_opts)
|
def transitions(trans_opts)
|
||||||
|
# Create a separate transition for each from state to the given state
|
||||||
Array(trans_opts[:from]).each do |s|
|
Array(trans_opts[:from]).each do |s|
|
||||||
@transitions << AASM::SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym}))
|
@transitions << AASM::SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym}))
|
||||||
end
|
end
|
||||||
|
# Create a transition if to is specified without from (transitions from ANY state)
|
||||||
|
@transitions << AASM::SupportingClasses::StateTransition.new(trans_opts) if @transitions.empty? && trans_opts[:to]
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,9 +9,14 @@ class Silencer
|
||||||
event :cry do
|
event :cry do
|
||||||
transitions :from => :silent, :to => :crying
|
transitions :from => :silent, :to => :crying
|
||||||
end
|
end
|
||||||
|
|
||||||
event :smile do
|
event :smile do
|
||||||
transitions :from => :crying, :to => :smiling
|
transitions :from => :crying, :to => :smiling
|
||||||
end
|
end
|
||||||
|
|
||||||
|
event :smile_any do
|
||||||
|
transitions :to => :smiling
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,6 +20,12 @@ describe 'transitions' do
|
||||||
sub.should be_silent
|
sub.should be_silent
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should not raise an exception when from is nil even if whiny' do
|
||||||
|
silencer = Silencer.new
|
||||||
|
silencer.smile_any!.should be_true
|
||||||
|
silencer.should be_smiling
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe AASM::SupportingClasses::StateTransition do
|
describe AASM::SupportingClasses::StateTransition do
|
||||||
|
|
Loading…
Reference in a new issue