Merge branch 'stiff-master' into master_merge_stiff
Conflicts: README.md lib/aasm/supporting_classes/event.rb
This commit is contained in:
commit
6f9be86282
|
@ -85,6 +85,12 @@ class Job
|
|||
end
|
||||
|
||||
event :sleep do
|
||||
after do
|
||||
...
|
||||
end
|
||||
error do |e|
|
||||
...
|
||||
end
|
||||
transitions :from => :running, :to => :sleeping
|
||||
end
|
||||
end
|
||||
|
@ -129,6 +135,9 @@ Also, you can pass parameters to events:
|
|||
|
||||
In this case the `set_process` would be called with `:defagmentation` argument.
|
||||
|
||||
In case of an error during the event processing the error is rescued and passed to `:error`
|
||||
callback, which can handle it or re-raise it for further propagation.
|
||||
|
||||
### Guards
|
||||
|
||||
Let's assume you want to allow particular transitions only if a defined condition is
|
||||
|
|
|
@ -184,7 +184,7 @@ private
|
|||
persist_successful = true
|
||||
if persist
|
||||
persist_successful = aasm_set_current_state_with_persistence(new_state_name)
|
||||
event.execute_success_callback(self) if persist_successful
|
||||
event.fire_callbacks(:success, self) if persist_successful
|
||||
else
|
||||
self.aasm_current_state = new_state_name
|
||||
end
|
||||
|
@ -213,7 +213,7 @@ private
|
|||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
event.execute_error_callback(self, e)
|
||||
event.fire_callbacks(:error, self, e) || raise(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module AASM
|
||||
module SupportingClasses
|
||||
class Event
|
||||
attr_reader :name, :success, :options
|
||||
attr_reader :name, :options
|
||||
|
||||
def initialize(name, options = {}, &block)
|
||||
@name = name
|
||||
|
@ -40,11 +40,8 @@ module AASM
|
|||
@transitions
|
||||
end
|
||||
|
||||
def fire_callbacks(action, record)
|
||||
action = @options[action]
|
||||
action.is_a?(Array) ?
|
||||
action.each {|a| _fire_callbacks(a, record)} :
|
||||
_fire_callbacks(action, record)
|
||||
def fire_callbacks(action, record, *args)
|
||||
invoke_callbacks(@options[action], record, args)
|
||||
end
|
||||
|
||||
def ==(event)
|
||||
|
@ -55,45 +52,13 @@ module AASM
|
|||
end
|
||||
end
|
||||
|
||||
def execute_success_callback(obj, success = nil)
|
||||
callback = success || @success
|
||||
case(callback)
|
||||
when String, Symbol
|
||||
obj.send(callback)
|
||||
when Proc
|
||||
callback.call(obj)
|
||||
when Array
|
||||
callback.each{|meth|self.execute_success_callback(obj, meth)}
|
||||
end
|
||||
end
|
||||
|
||||
def execute_error_callback(obj, error, error_callback=nil)
|
||||
callback = error_callback || @error
|
||||
raise error unless callback
|
||||
case(callback)
|
||||
when String, Symbol
|
||||
raise NoMethodError unless obj.respond_to?(callback.to_sym)
|
||||
obj.send(callback, error)
|
||||
when Proc
|
||||
callback.call(obj, error)
|
||||
when Array
|
||||
callback.each{|meth|self.execute_error_callback(obj, error, meth)}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update(options = {}, &block)
|
||||
if options.key?(:success) then
|
||||
@success = options[:success]
|
||||
end
|
||||
if options.key?(:error) then
|
||||
@error = options[:error]
|
||||
end
|
||||
@options = options
|
||||
if block then
|
||||
instance_eval(&block)
|
||||
end
|
||||
@options = options
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -123,15 +88,23 @@ module AASM
|
|||
result
|
||||
end
|
||||
|
||||
def _fire_callbacks(action, record)
|
||||
case action
|
||||
def invoke_callbacks(code, record, args)
|
||||
case code
|
||||
when Symbol, String
|
||||
record.send(action)
|
||||
record.send(code, *args)
|
||||
true
|
||||
when Proc
|
||||
record.instance_eval &action
|
||||
record.instance_exec(*args, &code)
|
||||
true
|
||||
when Array
|
||||
code.each {|a| invoke_callbacks(a, record, args)}
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
## DSL interface
|
||||
def transitions(trans_opts)
|
||||
# Create a separate transition for each from state to the given state
|
||||
Array(trans_opts[:from]).each do |s|
|
||||
|
@ -141,6 +114,13 @@ module AASM
|
|||
@transitions << AASM::SupportingClasses::StateTransition.new(trans_opts) if @transitions.empty? && trans_opts[:to]
|
||||
end
|
||||
|
||||
[:after, :before, :error, :success].each do |callback_name|
|
||||
define_method callback_name do |*args, &block|
|
||||
options[callback_name] = Array(options[callback_name])
|
||||
options[callback_name] << block if block
|
||||
options[callback_name] += Array(args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end # SupportingClasses
|
||||
end # AASM
|
||||
|
|
|
@ -3,6 +3,8 @@ require 'spec_helper'
|
|||
describe 'adding an event' do
|
||||
let(:event) do
|
||||
AASM::SupportingClasses::Event.new(:close_order, {:success => :success_callback}) do
|
||||
before :before_callback
|
||||
after :after_callback
|
||||
transitions :to => :closed, :from => [:open, :received]
|
||||
end
|
||||
end
|
||||
|
@ -12,7 +14,15 @@ describe 'adding an event' do
|
|||
end
|
||||
|
||||
it 'should set the success callback' do
|
||||
event.success.should == :success_callback
|
||||
event.options[:success].should == :success_callback
|
||||
end
|
||||
|
||||
it 'should set the after callback' do
|
||||
event.options[:after].should == [:after_callback]
|
||||
end
|
||||
|
||||
it 'should set the before callback' do
|
||||
event.options[:before].should == [:before_callback]
|
||||
end
|
||||
|
||||
it 'should create transitions' do
|
||||
|
@ -82,69 +92,125 @@ describe 'firing an event' do
|
|||
|
||||
end
|
||||
|
||||
describe 'executing the success callback' do
|
||||
describe 'should fire callbacks' do
|
||||
describe 'success' do
|
||||
it "if it's a symbol" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_symbol, :success => :symbol_success_callback do
|
||||
transitions :to => :symbol, :from => [:initial]
|
||||
end
|
||||
}
|
||||
|
||||
it "should send the success callback if it's a symbol" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_symbol, :success => :symbol_success_callback do
|
||||
transitions :to => :symbol, :from => [:initial]
|
||||
end
|
||||
}
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:symbol_success_callback)
|
||||
model.with_symbol!
|
||||
end
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:symbol_success_callback)
|
||||
model.with_symbol!
|
||||
it "if it's a string" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_string, :success => 'string_success_callback' do
|
||||
transitions :to => :string, :from => [:initial]
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:string_success_callback)
|
||||
model.with_string!
|
||||
end
|
||||
|
||||
it "if passed an array of strings and/or symbols" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_array, :success => [:success_callback1, 'success_callback2'] do
|
||||
transitions :to => :array, :from => [:initial]
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:success_callback1)
|
||||
model.should_receive(:success_callback2)
|
||||
model.with_array!
|
||||
end
|
||||
|
||||
it "if passed an array of strings and/or symbols and/or procs" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { proc_success_callback }] do
|
||||
transitions :to => :array, :from => [:initial]
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:success_callback1)
|
||||
model.should_receive(:success_callback2)
|
||||
model.should_receive(:proc_success_callback)
|
||||
model.with_array_including_procs!
|
||||
end
|
||||
|
||||
it "if it's a proc" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_proc, :success => lambda { proc_success_callback } do
|
||||
transitions :to => :proc, :from => [:initial]
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:proc_success_callback)
|
||||
model.with_proc!
|
||||
end
|
||||
end
|
||||
|
||||
it "should send the success callback if it's a string" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_string, :success => 'string_success_callback' do
|
||||
transitions :to => :string, :from => [:initial]
|
||||
describe 'after' do
|
||||
it "if they set different ways" do
|
||||
ThisNameBetterNotBeInUse.instance_eval do
|
||||
aasm_event :with_afters, :after => :do_one_thing_after do
|
||||
after do
|
||||
do_another_thing_after_too
|
||||
end
|
||||
after do
|
||||
do_third_thing_at_last
|
||||
end
|
||||
transitions :to => :proc, :from => [:initial]
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:string_success_callback)
|
||||
model.with_string!
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:do_one_thing_after).once.ordered
|
||||
model.should_receive(:do_another_thing_after_too).once.ordered
|
||||
model.should_receive(:do_third_thing_at_last).once.ordered
|
||||
model.with_afters!
|
||||
end
|
||||
end
|
||||
|
||||
it "should call each success callback if passed an array of strings and/or symbols" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_array, :success => [:success_callback1, 'success_callback2'] do
|
||||
transitions :to => :array, :from => [:initial]
|
||||
describe 'before' do
|
||||
it "if it's a proc" do
|
||||
ThisNameBetterNotBeInUse.instance_eval do
|
||||
aasm_event :before_as_proc do
|
||||
before do
|
||||
do_something_before
|
||||
end
|
||||
transitions :to => :proc, :from => [:initial]
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:success_callback1)
|
||||
model.should_receive(:success_callback2)
|
||||
model.with_array!
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:do_something_before).once
|
||||
model.before_as_proc!
|
||||
end
|
||||
end
|
||||
|
||||
it "should call each success callback if passed an array of strings and/or symbols and/or procs" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { |obj| obj.proc_success_callback }] do
|
||||
transitions :to => :array, :from => [:initial]
|
||||
end
|
||||
}
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:success_callback1)
|
||||
model.should_receive(:success_callback2)
|
||||
model.should_receive(:proc_success_callback)
|
||||
model.with_array_including_procs!
|
||||
end
|
||||
|
||||
it "should call the success callback if it's a proc" do
|
||||
ThisNameBetterNotBeInUse.instance_eval {
|
||||
aasm_event :with_proc, :success => lambda { |obj| obj.proc_success_callback } do
|
||||
it 'in right order' do
|
||||
ThisNameBetterNotBeInUse.instance_eval do
|
||||
aasm_event :in_right_order, :after => :do_something_after do
|
||||
before do
|
||||
do_something_before
|
||||
end
|
||||
transitions :to => :proc, :from => [:initial]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
model = ThisNameBetterNotBeInUse.new
|
||||
model.should_receive(:proc_success_callback)
|
||||
model.with_proc!
|
||||
model.should_receive(:do_something_before).once.ordered
|
||||
model.should_receive(:do_something_after).once.ordered
|
||||
model.in_right_order!
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue