statesman 8.0.2 → 8.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +68 -2
- data/lib/statesman/machine.rb +4 -0
- data/lib/statesman/version.rb +1 -1
- data/spec/statesman/machine_spec.rb +28 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d099ca7f60641163125a158ca189d41b571a46e4da8d5277a9391ff12df69e4
|
4
|
+
data.tar.gz: 5a33e698ded14cbc080f6d3e385d4d00d8191b5d1887e0b4fb062d592a35214f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b7e63cd44278ca20c9aac95b6ff1372b83131d5df988b72d6fabfbbc98057917f33bc6cdbc447c2d1d04f075ac215e58eb5e0beb09d0fd7d2d16e672cebacd2
|
7
|
+
data.tar.gz: 63588d5869538bab0f4a7900f2761ed3bcfb124895485d2fc1667ec159763e4fad69327af25d7221f113f6c43396aabb3d8548085d6bb25229487c5d19ba11c0
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -30,7 +30,7 @@ protection.
|
|
30
30
|
To get started, just add Statesman to your `Gemfile`, and then run `bundle`:
|
31
31
|
|
32
32
|
```ruby
|
33
|
-
gem 'statesman', '~>
|
33
|
+
gem 'statesman', '~> 8.0.3'
|
34
34
|
```
|
35
35
|
|
36
36
|
## Usage
|
@@ -109,6 +109,8 @@ Order.first.state_machine.allowed_transitions # => ["checking_out", "cancelled"]
|
|
109
109
|
Order.first.state_machine.can_transition_to?(:cancelled) # => true/false
|
110
110
|
Order.first.state_machine.transition_to(:cancelled, optional: :metadata) # => true/false
|
111
111
|
Order.first.state_machine.transition_to!(:cancelled) # => true/exception
|
112
|
+
Order.first.state_machine.last_transition # => transition model or nil
|
113
|
+
Order.first.state_machine.last_transition_to(:pending) # => transition model or nil
|
112
114
|
|
113
115
|
Order.in_state(:cancelled) # => [#<Order id: "123">]
|
114
116
|
Order.not_in_state(:checking_out) # => [#<Order id: "123">]
|
@@ -159,7 +161,8 @@ class Order < ActiveRecord::Base
|
|
159
161
|
|
160
162
|
# Optionally delegate some methods
|
161
163
|
|
162
|
-
delegate :can_transition_to?,
|
164
|
+
delegate :can_transition_to?,
|
165
|
+
:current_state, :history, :last_transition, :last_transition_to,
|
163
166
|
:transition_to!, :transition_to, :in_state?, to: :state_machine
|
164
167
|
end
|
165
168
|
```
|
@@ -335,6 +338,9 @@ Returns a sorted array of all transition objects.
|
|
335
338
|
#### `Machine#last_transition`
|
336
339
|
Returns the most recent transition object.
|
337
340
|
|
341
|
+
#### `Machine#last_transition_to(:state)`
|
342
|
+
Returns the most recent transition object to a given state.
|
343
|
+
|
338
344
|
#### `Machine#allowed_transitions`
|
339
345
|
Returns an array of states you can `transition_to` from current state.
|
340
346
|
|
@@ -351,6 +357,66 @@ Transition to the passed state, returning `true` on success. Swallows all
|
|
351
357
|
Statesman exceptions and returns false on failure. (NB. if your guard or
|
352
358
|
callback code throws an exception, it will not be caught.)
|
353
359
|
|
360
|
+
|
361
|
+
## Errors
|
362
|
+
|
363
|
+
### Initialization errors
|
364
|
+
These errors are raised when the Machine and/or Model is initialized. A simple spec like
|
365
|
+
```ruby
|
366
|
+
expect { OrderStateMachine.new(Order.new, transition_class: OrderTransition) }.to_not raise_error
|
367
|
+
```
|
368
|
+
will expose these errors as part of your test suite
|
369
|
+
|
370
|
+
#### InvalidStateError
|
371
|
+
Raised if:
|
372
|
+
* Attempting to define a transition without a `to` state.
|
373
|
+
* Attempting to define a transition with a non-existent state.
|
374
|
+
* Attempting to define multiple states as `initial`.
|
375
|
+
|
376
|
+
#### InvalidTransitionError
|
377
|
+
Raised if:
|
378
|
+
* Attempting to define a callback `from` a state that has no valid transitions (A terminal state).
|
379
|
+
* Attempting to define a callback `to` the `initial` state if that state has no transitions to it.
|
380
|
+
* Attempting to define a callback with `from` and `to` where any of the pairs have no transition between them.
|
381
|
+
|
382
|
+
#### InvalidCallbackError
|
383
|
+
Raised if:
|
384
|
+
* Attempting to define a callback without a block.
|
385
|
+
|
386
|
+
#### UnserializedMetadataError
|
387
|
+
Raised if:
|
388
|
+
* ActiveRecord is configured to not serialize the `metadata` attribute into
|
389
|
+
to Database column backing it. See the `Using PostgreSQL JSON column` section.
|
390
|
+
|
391
|
+
#### IncompatibleSerializationError
|
392
|
+
Raised if:
|
393
|
+
* There is a mismatch between the column type of the `metadata` in the
|
394
|
+
Database and the model. See the `Using PostgreSQL JSON column` section.
|
395
|
+
|
396
|
+
#### MissingTransitionAssociation
|
397
|
+
Raised if:
|
398
|
+
* The model that `Statesman::Adapters::ActiveRecordQueries` is included in
|
399
|
+
does not have a `has_many` association to the `transition_class`.
|
400
|
+
|
401
|
+
### Runtime errors
|
402
|
+
These errors are raised by `transition_to!`. Using `transition_to` will
|
403
|
+
supress `GuardFailedError` and `TransitionFailedError` and return `false` instead.
|
404
|
+
|
405
|
+
#### GuardFailedError
|
406
|
+
Raised if:
|
407
|
+
* A guard callback between `from` and `to` state returned a falsey value.
|
408
|
+
|
409
|
+
#### TransitionFailedError
|
410
|
+
Raised if:
|
411
|
+
* A transition is attempted but `current_state -> new_state` is not a valid pair.
|
412
|
+
|
413
|
+
#### TransitionConflictError
|
414
|
+
Raised if:
|
415
|
+
* A database conflict affecting the `sort_key` or `most_recent` columns occurs
|
416
|
+
when attempting a transition.
|
417
|
+
Retried automatically if it occurs wrapped in `retry_conflicts`.
|
418
|
+
|
419
|
+
|
354
420
|
## Model scopes
|
355
421
|
|
356
422
|
A mixin is provided for the ActiveRecord adapter which adds scopes to easily
|
data/lib/statesman/machine.rb
CHANGED
@@ -209,6 +209,10 @@ module Statesman
|
|
209
209
|
@storage_adapter.last(force_reload: force_reload)
|
210
210
|
end
|
211
211
|
|
212
|
+
def last_transition_to(state)
|
213
|
+
history.reverse.find { |transition| transition.to_state.to_sym == state.to_sym }
|
214
|
+
end
|
215
|
+
|
212
216
|
def can_transition_to?(new_state, metadata = {})
|
213
217
|
validate_transition(from: current_state,
|
214
218
|
to: new_state,
|
data/lib/statesman/version.rb
CHANGED
@@ -537,6 +537,34 @@ describe Statesman::Machine do
|
|
537
537
|
end
|
538
538
|
end
|
539
539
|
|
540
|
+
describe "#last_transition_to" do
|
541
|
+
subject { instance.last_transition_to(:y) }
|
542
|
+
|
543
|
+
before do
|
544
|
+
machine.class_eval do
|
545
|
+
state :x, initial: true
|
546
|
+
state :y
|
547
|
+
state :z
|
548
|
+
transition from: :x, to: :y
|
549
|
+
transition from: :y, to: :z
|
550
|
+
transition from: :z, to: :y
|
551
|
+
end
|
552
|
+
|
553
|
+
instance.transition_to!(:y)
|
554
|
+
instance.transition_to!(:z)
|
555
|
+
end
|
556
|
+
|
557
|
+
let(:instance) { machine.new(my_model) }
|
558
|
+
|
559
|
+
it { is_expected.to have_attributes(to_state: "y") }
|
560
|
+
|
561
|
+
context "when there are 2 transitions to the state" do
|
562
|
+
before { instance.transition_to!(:y) }
|
563
|
+
|
564
|
+
it { is_expected.to eq(instance.last_transition) }
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
540
568
|
describe "#can_transition_to?" do
|
541
569
|
subject(:can_transition_to?) { instance.can_transition_to?(new_state, metadata) }
|
542
570
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: statesman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.0.
|
4
|
+
version: 8.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GoCardless
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ammeter
|