mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
support event guards #85
This commit is contained in:
parent
39f85dbfdf
commit
5f8be13c8c
5 changed files with 80 additions and 16 deletions
|
@ -6,9 +6,10 @@
|
|||
|
||||
## 3.1.0 (not yet released)
|
||||
|
||||
* support multiple guards per transition
|
||||
* allow configuring behavior of nested transactions (see [issue #107](https://github.com/aasm/aasm/issues/107))
|
||||
* validating the current state (see [issue #95](https://github.com/aasm/aasm/issues/95), thanks to [@ivantsepp](https://github.com/ivantsepp))
|
||||
* allow configuring behavior of nested transactions (see [issue #107](https://github.com/aasm/aasm/issues/107))
|
||||
* support multiple guards per transition
|
||||
* support event guards (see [issue #85](https://github.com/aasm/aasm/issues/85))
|
||||
|
||||
## 3.0.26
|
||||
|
||||
|
|
11
README.md
11
README.md
|
@ -196,11 +196,22 @@ job.sleep # => raises AASM::InvalidTransition
|
|||
You can even provide a number of guards, which all have to succeed to proceed
|
||||
|
||||
```ruby
|
||||
def walked_the_dog?; ...; end
|
||||
|
||||
event :sleep do
|
||||
transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?, :walked_the_dog?]
|
||||
end
|
||||
```
|
||||
|
||||
If you want to provide guards for all transitions withing an event, you can use event guards
|
||||
|
||||
```ruby
|
||||
event :sleep, :guards => [:walked_the_dog?] do
|
||||
transitions :from => :running, :to => :sleeping, :guards => [:cleaning_needed?]
|
||||
transitions :from => :cleaning, :to => :sleeping
|
||||
end
|
||||
```
|
||||
|
||||
### ActiveRecord
|
||||
|
||||
AASM comes with support for ActiveRecord and allows automatical persisting of the object's
|
||||
|
|
|
@ -6,6 +6,7 @@ module AASM
|
|||
def initialize(name, options = {}, &block)
|
||||
@name = name
|
||||
@transitions = []
|
||||
@guards = Array(options[:guard] || options[:guards])
|
||||
update(options, &block)
|
||||
end
|
||||
|
||||
|
@ -57,18 +58,28 @@ module AASM
|
|||
## DSL interface
|
||||
def transitions(definitions=nil)
|
||||
if definitions # define new transitions
|
||||
# Create a separate transition for each from state to the given state
|
||||
# Create a separate transition for each from-state to the given state
|
||||
Array(definitions[:from]).each do |s|
|
||||
@transitions << AASM::Transition.new(definitions.merge({:from => s.to_sym}))
|
||||
@transitions << AASM::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)))
|
||||
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))
|
||||
end
|
||||
# Create a transition if to is specified without from (transitions from ANY state)
|
||||
@transitions << AASM::Transition.new(definitions) if @transitions.empty? && definitions[:to]
|
||||
end
|
||||
@transitions
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attach_event_guards(definitions)
|
||||
unless @guards.empty?
|
||||
given_guards = Array(definitions.delete(:guard) || definitions.delete(:guards))
|
||||
definitions[:guards] = given_guards + @guards
|
||||
end
|
||||
definitions
|
||||
end
|
||||
|
||||
def update(options = {}, &block)
|
||||
@options = options
|
||||
if block then
|
||||
|
|
|
@ -11,6 +11,7 @@ class Guardian
|
|||
event :use_one_guard_that_fails do
|
||||
transitions :from => :alpha, :to => :beta, :guard => :fail
|
||||
end
|
||||
|
||||
event :use_guards_that_succeed do
|
||||
transitions :from => :alpha, :to => :beta, :guards => [:succeed, :another_succeed]
|
||||
end
|
||||
|
@ -20,18 +21,28 @@ class Guardian
|
|||
event :use_guards_where_the_second_fails do
|
||||
transitions :from => :alpha, :to => :beta, :guards => [:fail, :succeed]
|
||||
end
|
||||
|
||||
event :use_event_guards_that_succeed, :guards => [:succeed, :another_succeed] do
|
||||
transitions :from => :alpha, :to => :beta
|
||||
end
|
||||
event :use_event_and_transition_guards_that_succeed, :guards => [:succeed, :another_succeed] do
|
||||
transitions :from => :alpha, :to => :beta, :guards => [:more_succeed]
|
||||
end
|
||||
event :use_event_guards_where_the_first_fails, :guards => [:succeed, :fail] do
|
||||
transitions :from => :alpha, :to => :beta
|
||||
end
|
||||
event :use_event_guards_where_the_second_fails, :guards => [:fail, :succeed] do
|
||||
transitions :from => :alpha, :to => :beta, :guard => :another_succeed
|
||||
end
|
||||
event :use_event_and_transition_guards_where_third_fails, :guards => [:succeed, :another_succeed] do
|
||||
transitions :from => :alpha, :to => :beta, :guards => [:fail]
|
||||
end
|
||||
end
|
||||
|
||||
def fail
|
||||
false
|
||||
end
|
||||
def fail; false; end
|
||||
|
||||
def succeed
|
||||
true
|
||||
end
|
||||
|
||||
def another_succeed
|
||||
true
|
||||
end
|
||||
def succeed; true; end
|
||||
def another_succeed; true; end
|
||||
def more_succeed; true; end
|
||||
|
||||
end
|
||||
|
|
|
@ -28,3 +28,33 @@ describe "per-transition guards" do
|
|||
expect(guardian).to be_alpha
|
||||
end
|
||||
end
|
||||
|
||||
describe "event guards" do
|
||||
let(:guardian) { Guardian.new }
|
||||
|
||||
it "allows the transition if the event guards succeed" do
|
||||
expect { guardian.use_event_guards_that_succeed! }.to_not raise_error
|
||||
expect(guardian).to be_beta
|
||||
end
|
||||
|
||||
it "allows the transition if the event and transition guards succeed" do
|
||||
expect { guardian.use_event_and_transition_guards_that_succeed! }.to_not raise_error
|
||||
expect(guardian).to be_beta
|
||||
end
|
||||
|
||||
it "stops the transition if the first event guard fails" do
|
||||
expect { guardian.use_event_guards_where_the_first_fails! }.to raise_error(AASM::InvalidTransition)
|
||||
expect(guardian).to be_alpha
|
||||
end
|
||||
|
||||
it "stops the transition if the second event guard fails" do
|
||||
expect { guardian.use_event_guards_where_the_second_fails! }.to raise_error(AASM::InvalidTransition)
|
||||
expect(guardian).to be_alpha
|
||||
end
|
||||
|
||||
it "stops the transition if the transition guard fails" do
|
||||
expect { guardian.use_event_and_transition_guards_where_third_fails! }.to raise_error(AASM::InvalidTransition)
|
||||
expect(guardian).to be_alpha
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue