diff --git a/lib/aasm/aasm.rb b/lib/aasm/aasm.rb index 790af8d..1606053 100644 --- a/lib/aasm/aasm.rb +++ b/lib/aasm/aasm.rb @@ -103,6 +103,7 @@ private persist_successful = aasm.set_current_state_with_persistence(new_state_name) if persist_successful yield if block_given? + event.fire_transition_callbacks(self, *process_args(event, old_state.name, *args)) event.fire_callbacks(:success, self) end else diff --git a/lib/aasm/core/event.rb b/lib/aasm/core/event.rb index aca4a1d..780e21e 100644 --- a/lib/aasm/core/event.rb +++ b/lib/aasm/core/event.rb @@ -7,6 +7,7 @@ module AASM::Core def initialize(name, options = {}, &block) @name = name @transitions = [] + @valid_transitions = {} @guards = Array(options[:guard] || options[:guards] || options[:if]) @unless = Array(options[:unless]) #TODO: This could use a better name @@ -48,6 +49,12 @@ module AASM::Core invoke_callbacks(@options[callback_name], record, args) end + def fire_transition_callbacks(obj, *args) + from_state = obj.aasm.current_state + transition = @valid_transitions[from_state] + @valid_transitions[from_state].invoke_success_callbacks(obj, *args) if transition + end + def ==(event) if event.is_a? Symbol name == event @@ -85,7 +92,6 @@ module AASM::Core definitions end - # Execute if test == false, otherwise return true/false depending on whether it would fire def _fire(obj, options={}, to_state=nil, *args) result = options[:test_only] ? false : nil if @transitions.map(&:from).any? @@ -112,6 +118,7 @@ module AASM::Core if options[:test_only] # result = true else + Array(transition.to).each {|to| @valid_transitions[to] = transition } transition.execute(obj, *args) end diff --git a/lib/aasm/core/transition.rb b/lib/aasm/core/transition.rb index cbb11a2..65a49ee 100644 --- a/lib/aasm/core/transition.rb +++ b/lib/aasm/core/transition.rb @@ -43,6 +43,10 @@ module AASM::Core @from == value end + def invoke_success_callbacks(obj, *args) + _fire_callbacks(@success, obj, args) + end + private def invoke_callbacks_compatible_with_guard(code, record, args, options={}) @@ -73,5 +77,19 @@ module AASM::Core end end + def _fire_callbacks(code, record, args) + case code + when Symbol, String + arity = record.send(:method, code.to_sym).arity + record.send(code, *(arity < 0 ? args : args[0...arity])) + when Proc + code.arity == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code) + when Array + @success.map {|a| _fire_callbacks(a, obj, args)} + else + true + end + end + end end # AASM