allowed :to array and :on_transition callback, with tests
This commit is contained in:
parent
216b48e519
commit
8a7320b9d0
12
lib/aasm.rb
12
lib/aasm.rb
|
@ -49,12 +49,12 @@ module AASM
|
||||||
sm.events[name] = AASM::SupportingClasses::Event.new(name, options, &block)
|
sm.events[name] = AASM::SupportingClasses::Event.new(name, options, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method("#{name.to_s}!") do
|
define_method("#{name.to_s}!") do |*args|
|
||||||
aasm_fire_event(name, true)
|
aasm_fire_event(name, true, *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method("#{name.to_s}") do
|
define_method("#{name.to_s}") do |*args|
|
||||||
aasm_fire_event(name, false)
|
aasm_fire_event(name, false, *args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -111,10 +111,10 @@ module AASM
|
||||||
self.class.aasm_states.find {|s| s == name}
|
self.class.aasm_states.find {|s| s == name}
|
||||||
end
|
end
|
||||||
|
|
||||||
def aasm_fire_event(name, persist)
|
def aasm_fire_event(name, persist, *args)
|
||||||
aasm_state_object_for_state(aasm_current_state).call_action(:exit, self)
|
aasm_state_object_for_state(aasm_current_state).call_action(:exit, self)
|
||||||
|
|
||||||
new_state = self.class.aasm_events[name].fire(self)
|
new_state = self.class.aasm_events[name].fire(self, *args)
|
||||||
|
|
||||||
unless new_state.nil?
|
unless new_state.nil?
|
||||||
aasm_state_object_for_state(new_state).call_action(:enter, self)
|
aasm_state_object_for_state(new_state).call_action(:enter, self)
|
||||||
|
|
|
@ -12,14 +12,16 @@ module AASM
|
||||||
instance_eval(&block) if block
|
instance_eval(&block) if block
|
||||||
end
|
end
|
||||||
|
|
||||||
def fire(obj)
|
def fire(obj, to_state=nil, *args)
|
||||||
transitions = @transitions.select { |t| t.from == obj.aasm_current_state }
|
transitions = @transitions.select { |t| t.from == obj.aasm_current_state }
|
||||||
raise AASM::InvalidTransition if transitions.size == 0
|
raise AASM::InvalidTransition if transitions.size == 0
|
||||||
|
|
||||||
next_state = nil
|
next_state = nil
|
||||||
transitions.each do |transition|
|
transitions.each do |transition|
|
||||||
|
next if to_state and !Array(transition.to).include?(to_state)
|
||||||
if transition.perform(obj)
|
if transition.perform(obj)
|
||||||
next_state = transition.to
|
next_state = to_state || Array(transition.to).first
|
||||||
|
transition.execute(obj, *args)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module AASM
|
||||||
attr_reader :from, :to, :opts
|
attr_reader :from, :to, :opts
|
||||||
|
|
||||||
def initialize(opts)
|
def initialize(opts)
|
||||||
@from, @to, @guard = opts[:from], opts[:to], opts[:guard]
|
@from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition]
|
||||||
@opts = opts
|
@opts = opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -19,6 +19,15 @@ module AASM
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def execute(obj, *args)
|
||||||
|
case @on_transition
|
||||||
|
when Symbol, String
|
||||||
|
obj.send(@on_transition, *args)
|
||||||
|
when Proc
|
||||||
|
@on_transition.call(obj, *args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def ==(obj)
|
def ==(obj)
|
||||||
@from == obj.from && @to == obj.to
|
@from == obj.from && @to == obj.to
|
||||||
end
|
end
|
||||||
|
|
|
@ -270,3 +270,72 @@ describe Baz do
|
||||||
Baz.aasm_events.should == Bar.aasm_events
|
Baz.aasm_events.should == Bar.aasm_events
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class ChetanPatil
|
||||||
|
include AASM
|
||||||
|
aasm_initial_state :sleeping
|
||||||
|
aasm_state :sleeping
|
||||||
|
aasm_state :showering
|
||||||
|
aasm_state :working
|
||||||
|
aasm_state :dating
|
||||||
|
|
||||||
|
aasm_event :wakeup do
|
||||||
|
transitions :from => :sleeping, :to => [:showering, :working]
|
||||||
|
end
|
||||||
|
|
||||||
|
aasm_event :dress do
|
||||||
|
transitions :from => :sleeping, :to => :working, :on_transition => :wear_clothes
|
||||||
|
transitions :from => :showering, :to => [:working, :dating], :on_transition => Proc.new { |obj, *args| obj.wear_clothes(*args) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def wear_clothes(shirt_color, trouser_type)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe ChetanPatil do
|
||||||
|
it 'should transition to specified next state (sleeping to showering)' do
|
||||||
|
cp = ChetanPatil.new
|
||||||
|
cp.wakeup! :showering
|
||||||
|
|
||||||
|
cp.aasm_current_state.should == :showering
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should transition to specified next state (sleeping to working)' do
|
||||||
|
cp = ChetanPatil.new
|
||||||
|
cp.wakeup! :working
|
||||||
|
|
||||||
|
cp.aasm_current_state.should == :working
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should transition to default (first or showering) state' do
|
||||||
|
cp = ChetanPatil.new
|
||||||
|
cp.wakeup!
|
||||||
|
|
||||||
|
cp.aasm_current_state.should == :showering
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should transition to default state when on_transition invoked' do
|
||||||
|
cp = ChetanPatil.new
|
||||||
|
cp.dress!(nil, 'purple', 'dressy')
|
||||||
|
|
||||||
|
cp.aasm_current_state.should == :working
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should call on_transition method with args' do
|
||||||
|
cp = ChetanPatil.new
|
||||||
|
cp.wakeup! :showering
|
||||||
|
|
||||||
|
cp.should_receive(:wear_clothes).with('blue', 'jeans')
|
||||||
|
cp.dress! :working, 'blue', 'jeans'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should call on_transition proc' do
|
||||||
|
cp = ChetanPatil.new
|
||||||
|
cp.wakeup! :showering
|
||||||
|
|
||||||
|
cp.should_receive(:wear_clothes).with('purple', 'slacks')
|
||||||
|
cp.dress!(:dating, 'purple', 'slacks')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue