bugfix: really support block-guards (defined within a transition block) #186
This commit is contained in:
parent
9701a447d3
commit
4fdc2a73b5
|
@ -4,6 +4,10 @@
|
|||
|
||||
* `aasm_human_event_name` is deprecated, use `aasm.human_event_name` instead
|
||||
|
||||
## 4.0.2
|
||||
|
||||
* bugfix: really support block-guards (defined within a transition block) (see [issue #186](https://github.com/aasm/aasm/issues/186) for details)
|
||||
|
||||
## 4.0.1
|
||||
|
||||
* fire guards only once per transition (see [issue #184](https://github.com/aasm/aasm/issues/184) for details)
|
||||
|
|
|
@ -57,15 +57,15 @@ module AASM
|
|||
end
|
||||
|
||||
## DSL interface
|
||||
def transitions(definitions=nil)
|
||||
def transitions(definitions=nil, &block)
|
||||
if definitions # define new transitions
|
||||
# Create a separate transition for each from-state to the given state
|
||||
Array(definitions[:from]).each do |s|
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)))
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
|
||||
end
|
||||
# Create a transition if :to is specified without :from (transitions from ANY state)
|
||||
if @transitions.empty? && definitions[:to]
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions))
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions), &block)
|
||||
end
|
||||
end
|
||||
@transitions
|
||||
|
|
|
@ -10,7 +10,7 @@ module AASM
|
|||
|
||||
@from = opts[:from]
|
||||
@to = opts[:to]
|
||||
@guards = Array(opts[:guard] || opts[:guards] || opts[:if])
|
||||
@guards = Array(opts[:guards]) + Array(opts[:guard]) + Array(opts[:if])
|
||||
@unless = Array(opts[:unless]) #TODO: This could use a better name
|
||||
|
||||
if opts[:on_transition]
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
class GuardWithinBlock
|
||||
include AASM
|
||||
|
||||
def initialize(options={})
|
||||
@fail_event_guard = options[:fail_event_guard]
|
||||
@fail_transition_guard = options[:fail_transition_guard]
|
||||
@log = options[:log]
|
||||
end
|
||||
|
||||
aasm do
|
||||
state :open, :initial => true,
|
||||
:before_enter => :before_enter_open,
|
||||
:enter => :enter_open,
|
||||
:after_enter => :after_enter_open,
|
||||
:before_exit => :before_exit_open,
|
||||
:exit => :exit_open,
|
||||
:after_exit => :after_exit_open
|
||||
|
||||
state :closed,
|
||||
:before_enter => :before_enter_closed,
|
||||
:enter => :enter_closed,
|
||||
:after_enter => :after_enter_closed,
|
||||
:before_exit => :before_exit_closed,
|
||||
:exit => :exit_closed,
|
||||
:after_exit => :after_exit_closed
|
||||
|
||||
event :close, :before => :before, :after => :after, :guard => :event_guard do
|
||||
transitions :to => :closed, :from => [:open], :after => :transitioning do
|
||||
guard do
|
||||
transition_guard
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
event :open, :before => :before, :after => :after do
|
||||
transitions :to => :open, :from => :closed
|
||||
end
|
||||
end
|
||||
|
||||
def log(text)
|
||||
puts text if @log
|
||||
end
|
||||
|
||||
def before_enter_open; log('before_enter_open'); end
|
||||
def enter_open; log('enter_open'); end
|
||||
def before_exit_open; log('before_exit_open'); end
|
||||
def after_enter_open; log('after_enter_open'); end
|
||||
def exit_open; log('exit_open'); end
|
||||
def after_exit_open; log('after_exit_open'); end
|
||||
|
||||
def before_enter_closed; log('before_enter_closed'); end
|
||||
def enter_closed; log('enter_closed'); end
|
||||
def before_exit_closed; log('before_exit_closed'); end
|
||||
def exit_closed; log('exit_closed'); end
|
||||
def after_enter_closed; log('after_enter_closed'); end
|
||||
def after_exit_closed; log('after_exit_closed'); end
|
||||
|
||||
def event_guard; log('event_guard'); !@fail_event_guard; end
|
||||
def transition_guard; log('transition_guard'); !@fail_transition_guard; end
|
||||
def transitioning; log('transitioning'); end
|
||||
|
||||
def before; log('before'); end
|
||||
def after; log('after'); end
|
||||
end
|
|
@ -47,26 +47,50 @@ describe 'callbacks for the new DSL' do
|
|||
}.to raise_error(AASM::InvalidTransition)
|
||||
end
|
||||
|
||||
it "does not run any state callback if the transition guard fails" do
|
||||
callback = CallbackNewDsl.new
|
||||
callback.aasm.current_state
|
||||
context "if the transition guard fails" do
|
||||
it "does not run any state callback if guard is defined inline" do
|
||||
callback = CallbackNewDsl.new
|
||||
callback.aasm.current_state
|
||||
|
||||
expect(callback).to receive(:before).once.ordered
|
||||
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
||||
expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
|
||||
expect(callback).to_not receive(:before_exit_open)
|
||||
expect(callback).to_not receive(:exit_open)
|
||||
expect(callback).to_not receive(:transitioning)
|
||||
expect(callback).to_not receive(:before_enter_closed)
|
||||
expect(callback).to_not receive(:enter_closed)
|
||||
expect(callback).to_not receive(:aasm_write_state)
|
||||
expect(callback).to_not receive(:after_exit_open)
|
||||
expect(callback).to_not receive(:after_enter_closed)
|
||||
expect(callback).to_not receive(:after)
|
||||
expect(callback).to receive(:before).once.ordered
|
||||
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
||||
expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
|
||||
expect(callback).to_not receive(:before_exit_open)
|
||||
expect(callback).to_not receive(:exit_open)
|
||||
expect(callback).to_not receive(:transitioning)
|
||||
expect(callback).to_not receive(:before_enter_closed)
|
||||
expect(callback).to_not receive(:enter_closed)
|
||||
expect(callback).to_not receive(:aasm_write_state)
|
||||
expect(callback).to_not receive(:after_exit_open)
|
||||
expect(callback).to_not receive(:after_enter_closed)
|
||||
expect(callback).to_not receive(:after)
|
||||
|
||||
expect {
|
||||
callback.close!
|
||||
}.to raise_error(AASM::InvalidTransition)
|
||||
expect {
|
||||
callback.close!
|
||||
}.to raise_error(AASM::InvalidTransition)
|
||||
end
|
||||
|
||||
it "does not run any state callback if guard is defined with block" do
|
||||
callback = GuardWithinBlock.new #(:log => true, :fail_transition_guard => true)
|
||||
callback.aasm.current_state
|
||||
|
||||
expect(callback).to receive(:before).once.ordered
|
||||
expect(callback).to receive(:event_guard).once.ordered.and_return(true)
|
||||
expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
|
||||
expect(callback).to_not receive(:before_exit_open)
|
||||
expect(callback).to_not receive(:exit_open)
|
||||
expect(callback).to_not receive(:transitioning)
|
||||
expect(callback).to_not receive(:before_enter_closed)
|
||||
expect(callback).to_not receive(:enter_closed)
|
||||
expect(callback).to_not receive(:aasm_write_state)
|
||||
expect(callback).to_not receive(:after_exit_open)
|
||||
expect(callback).to_not receive(:after_enter_closed)
|
||||
expect(callback).to_not receive(:after)
|
||||
|
||||
expect {
|
||||
callback.close!
|
||||
}.to raise_error(AASM::InvalidTransition)
|
||||
end
|
||||
end
|
||||
|
||||
it "should properly pass arguments" do
|
||||
|
|
Loading…
Reference in New Issue