From cd8a2ef12d86088e284952fb72021269632b4428 Mon Sep 17 00:00:00 2001 From: Ronnie Miller Date: Mon, 1 Feb 2016 20:22:43 -0800 Subject: [PATCH] Add option to use Class that responds to call for after transitions --- lib/aasm/core/transition.rb | 12 +++++++ spec/unit/transition_spec.rb | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/lib/aasm/core/transition.rb b/lib/aasm/core/transition.rb index 87bd0e0..81f2ec4 100644 --- a/lib/aasm/core/transition.rb +++ b/lib/aasm/core/transition.rb @@ -61,6 +61,18 @@ module AASM::Core result = (code.parameters.size == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code)) failures << code.source_location.join('#') unless result result + when Class + arity = code.instance_method(:initialize).arity + if arity == 0 + instance = code.new + elsif arity == 1 + instance = code.new(record) + else + instance = code.new(record, *args) + end + result = instance.call + failures << instance.method(:call).source_location.join('#') unless result + result when Array if options[:guard] # invoke guard callbacks diff --git a/spec/unit/transition_spec.rb b/spec/unit/transition_spec.rb index 05b313b..80302bf 100644 --- a/spec/unit/transition_spec.rb +++ b/spec/unit/transition_spec.rb @@ -300,3 +300,66 @@ describe AASM::Core::Transition, '- when executing the transition with an :after end end + +describe AASM::Core::Transition, '- when executing the transition with a Class' do + let(:state_machine) { AASM::StateMachine.new(:name) } + let(:event) { AASM::Core::Event.new(:event, state_machine) } + + class AfterTransitionClass + def initialize(record) + @record = record + end + + def call + "from: #{@record.aasm.from_state} to: #{@record.aasm.to_state}" + end + end + + class AfterTransitionClassWithArgs + def initialize(record, args) + @record = record + @args = args + end + + def call + "arg1: #{@args[:arg1]}, arg2: #{@args[:arg2]}" + end + end + + class AfterTransitionClassWithoutArgs + def call + 'success' + end + end + + it 'passes the record to the initialize method on the class to give access to the from_state and to_state' do + opts = {:from => 'foo', :to => 'bar', :after => AfterTransitionClass} + transition = AASM::Core::Transition.new(event, opts) + obj = double('object', :aasm => AASM::InstanceBase.new('object')) + + return_value = transition.execute(obj) + + expect(return_value).to eq('from: foo to: bar') + end + + it 'should pass args to the initialize method on the class if it accepts them' do + opts = {:from => 'foo', :to => 'bar', :after => AfterTransitionClassWithArgs} + st = AASM::Core::Transition.new(event, opts) + args = {:arg1 => '1', :arg2 => '2'} + obj = double('object', :aasm => 'aasm') + + return_value = st.execute(obj, args) + + expect(return_value).to eq('arg1: 1, arg2: 2') + end + + it 'should NOT pass args if the call method of the class if it does NOT accept them' do + opts = {:from => 'foo', :to => 'bar', :after => AfterTransitionClassWithoutArgs} + st = AASM::Core::Transition.new(event, opts) + obj = double('object', :aasm => 'aasm') + + return_value = st.execute(obj) + + expect(return_value).to eq('success') + end +end