diff --git a/.gitignore b/.gitignore index b3bf3d1..078ecca 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,4 @@ TODO alto .rspec .bundle - +tags diff --git a/lib/aasm/event.rb b/lib/aasm/event.rb index c62da51..05b3198 100644 --- a/lib/aasm/event.rb +++ b/lib/aasm/event.rb @@ -6,7 +6,8 @@ module AASM def initialize(name, options = {}, &block) @name = name @transitions = [] - @guards = Array(options[:guard] || options[:guards]) + @guards = Array(options[:guard] || options[:guards] || options[:if]) + @unless = Array(options[:unless]) #TODO: This could use a better name update(options, &block) end @@ -74,9 +75,13 @@ module AASM def attach_event_guards(definitions) unless @guards.empty? - given_guards = Array(definitions.delete(:guard) || definitions.delete(:guards)) + given_guards = Array(definitions.delete(:guard) || definitions.delete(:guards) || definitions.delete(:if)) definitions[:guards] = given_guards + @guards end + unless @unless.empty? + given_unless = Array(definitions.delete(:unless)) + definitions[:unless] = given_unless + @unless + end definitions end @@ -100,7 +105,7 @@ module AASM transitions.each do |transition| next if to_state and !Array(transition.to).include?(to_state) - if transition.perform(obj, *args) + if transition.allowed?(obj, *args) if test result = true else diff --git a/lib/aasm/transition.rb b/lib/aasm/transition.rb index 88c4dc2..e682fa8 100644 --- a/lib/aasm/transition.rb +++ b/lib/aasm/transition.rb @@ -6,13 +6,14 @@ module AASM def initialize(opts) @from = opts[:from] @to = opts[:to] - @guards = Array(opts[:guard] || opts[:guards]) + @guards = Array(opts[:guard] || opts[:guards] || opts[:if]) + @unless = Array(opts[:unless]) #TODO: This could use a better name @on_transition = opts[:on_transition] @opts = opts end # TODO: should be named allowed? or similar - def perform(obj, *args) + def allowed?(obj, *args) @guards.each do |guard| case guard when Symbol, String @@ -21,6 +22,15 @@ module AASM return false unless guard.call(obj, *args) end end + + @unless.each do |guard| + case guard + when Symbol, String + return false if obj.send(guard, *args) + when Proc + return false if guard.call(obj, *args) + end + end true end diff --git a/spec/unit/transition_spec.rb b/spec/unit/transition_spec.rb index 87fe791..6610ac6 100644 --- a/spec/unit/transition_spec.rb +++ b/spec/unit/transition_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'byebug' describe 'transitions' do @@ -100,7 +101,7 @@ describe AASM::Transition, '- when performing guard checks' do opts = {:from => 'foo', :to => 'bar'} st = AASM::Transition.new(opts) - expect(st.perform(nil)).to be_true + expect(st.allowed?(nil)).to be_true end it 'should call the method on the object if guard is a symbol' do @@ -110,7 +111,17 @@ describe AASM::Transition, '- when performing guard checks' do obj = double('object') expect(obj).to receive(:test) - st.perform(obj) + expect(st.allowed?(obj)).to be false + end + + it 'should call the method on the object if unless is a symbol' do + opts = {:from => 'foo', :to => 'bar', :unless => :test} + st = AASM::Transition.new(opts) + + obj = double('object') + expect(obj).to receive(:test) + + expect(st.allowed?(obj)).to be true end it 'should call the method on the object if guard is a string' do @@ -120,7 +131,17 @@ describe AASM::Transition, '- when performing guard checks' do obj = double('object') expect(obj).to receive(:test) - st.perform(obj) + expect(st.allowed?(obj)).to be false + end + + it 'should call the method on the object if unless is a string' do + opts = {:from => 'foo', :to => 'bar', :unless => 'test'} + st = AASM::Transition.new(opts) + + obj = double('object') + expect(obj).to receive(:test) + + expect(st.allowed?(obj)).to be true end it 'should call the proc passing the object if the guard is a proc' do @@ -130,7 +151,7 @@ describe AASM::Transition, '- when performing guard checks' do obj = double('object') expect(obj).to receive(:test) - st.perform(obj) + expect(st.allowed?(obj)).to be false end end