mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Merge branch 'master' into aasm4
Conflicts: CHANGELOG.md lib/aasm/event.rb lib/aasm/transition.rb
This commit is contained in:
commit
7d32335b60
8 changed files with 73 additions and 17 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -16,4 +16,4 @@ TODO
|
|||
alto
|
||||
.rspec
|
||||
.bundle
|
||||
|
||||
tags
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
* **DSL change**: renamed permissible states and events to permitted states events
|
||||
* removed deprecated methods (mostly the ones prefixed with `aasm_`)
|
||||
|
||||
## 3.5.0 (not yet released)
|
||||
|
||||
* support `if` and `unless` guard syntax: (see [issue #179](https://github.com/aasm/aasm/issues/179) and [issue #181](https://github.com/aasm/aasm/issues/181)), thanks to [@bigtunacan](https://github.com/bigtunacan)
|
||||
|
||||
## 3.4.0
|
||||
|
||||
* allow retrieving the current event (`aasm.current_event`) (see [issue #159](https://github.com/aasm/aasm/issues/159) and [issue #168](https://github.com/aasm/aasm/issues/168))
|
||||
|
|
14
README.md
14
README.md
|
@ -264,6 +264,20 @@ If you want to provide guards for all transitions within an event, you can use e
|
|||
end
|
||||
```
|
||||
|
||||
If you prefer a more Ruby-like guard syntax, you can use `if` and `unless` as well:
|
||||
|
||||
```ruby
|
||||
event :clean do
|
||||
transitions :from => :running, :to => :cleaning, :unless => :cleaning_needed?
|
||||
end
|
||||
|
||||
event :sleep do
|
||||
transitions :from => :running, :to => :sleeping, :if => :cleaning_needed?
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
### Transitions
|
||||
|
||||
In the event of having multiple transitions for an event, the first transition that successfully completes will stop other transitions in the same event from being processed.
|
||||
|
|
|
@ -7,7 +7,10 @@ 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
|
||||
|
||||
# from aasm4
|
||||
@options = options # QUESTION: .dup ?
|
||||
add_options_from_dsl(@options, [:after, :before, :error, :success], &block) if block
|
||||
end
|
||||
|
@ -72,8 +75,12 @@ module AASM
|
|||
|
||||
def attach_event_guards(definitions)
|
||||
unless @guards.empty?
|
||||
given_guards = Array(definitions.delete(:guard) || definitions.delete(:guards))
|
||||
definitions[:guards] = @guards + given_guards
|
||||
given_guards = Array(definitions.delete(:guard) || definitions.delete(:guards) || definitions.delete(:if))
|
||||
definitions[:guards] = @guards + given_guards # from aasm4
|
||||
end
|
||||
unless @unless.empty?
|
||||
given_unless = Array(definitions.delete(:unless))
|
||||
definitions[:unless] = given_unless + @unless
|
||||
end
|
||||
definitions
|
||||
end
|
||||
|
@ -99,7 +106,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
|
||||
|
|
|
@ -8,19 +8,24 @@ module AASM
|
|||
def initialize(opts, &block)
|
||||
add_options_from_dsl(opts, [:on_transition, :guard, :after], &block) if block
|
||||
|
||||
@from, @to, @guards = opts[:from], opts[:to], Array(opts[:guard] || opts[:guards])
|
||||
@from = opts[:from]
|
||||
@to = opts[:to]
|
||||
@guards = Array(opts[:guard] || opts[:guards] || opts[:if])
|
||||
@unless = Array(opts[:unless]) #TODO: This could use a better name
|
||||
|
||||
if opts[:on_transition]
|
||||
warn '[DEPRECATION] :on_transition is deprecated, use :after instead'
|
||||
opts[:after] = Array(opts[:after]) + Array(opts[:on_transition])
|
||||
end
|
||||
@after = Array(opts[:after])
|
||||
@after = @after[0] if @after.size == 1
|
||||
|
||||
@opts = opts
|
||||
end
|
||||
|
||||
# TODO: should be named allowed? or similar
|
||||
def perform(obj, *args)
|
||||
invoke_callbacks_compatible_with_guard(@guards, obj, args, :guard => true)
|
||||
def allowed?(obj, *args)
|
||||
invoke_callbacks_compatible_with_guard(@guards, obj, args, :guard => true) &&
|
||||
invoke_callbacks_compatible_with_guard(@unless, obj, args, :unless => true)
|
||||
end
|
||||
|
||||
def execute(obj, *args)
|
||||
|
@ -52,9 +57,14 @@ module AASM
|
|||
# QUESTION : record.instance_exec(*args, &code) ?
|
||||
code.arity == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code)
|
||||
when Array
|
||||
if options[:guard] # guard callbacks
|
||||
if options[:guard]
|
||||
# invoke guard callbacks
|
||||
code.all? {|a| invoke_callbacks_compatible_with_guard(a, record, args)}
|
||||
else # after callbacks
|
||||
elsif options[:unless]
|
||||
# invoke unless callbacks
|
||||
code.all? {|a| !invoke_callbacks_compatible_with_guard(a, record, args)}
|
||||
else
|
||||
# invoke after callbacks
|
||||
code.map {|a| invoke_callbacks_compatible_with_guard(a, record, args)}
|
||||
end
|
||||
else
|
||||
|
|
|
@ -4,6 +4,7 @@ class CallbackNewDsl
|
|||
def initialize(options={})
|
||||
@fail_event_guard = options[:fail_event_guard]
|
||||
@fail_transition_guard = options[:fail_transition_guard]
|
||||
@log = options[:log]
|
||||
end
|
||||
|
||||
aasm do
|
||||
|
@ -33,7 +34,7 @@ class CallbackNewDsl
|
|||
end
|
||||
|
||||
def log(text)
|
||||
# puts text
|
||||
puts text if @log
|
||||
end
|
||||
|
||||
def before_enter_open; log('before_enter_open'); end
|
||||
|
|
|
@ -26,7 +26,7 @@ describe 'callbacks for the new DSL' do
|
|||
end
|
||||
|
||||
it "does not run any state callback if the event guard fails" do
|
||||
callback = CallbackNewDsl.new
|
||||
callback = CallbackNewDsl.new(:log => false)
|
||||
callback.aasm.current_state
|
||||
|
||||
expect(callback).to receive(:before).once.ordered
|
||||
|
|
|
@ -124,7 +124,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
|
||||
|
@ -134,7 +134,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
|
||||
|
@ -144,7 +154,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
|
||||
|
@ -154,7 +174,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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue