aasm 4.12.0 → 4.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +5 -1
- data/Appraisals +2 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/README.md +102 -8
- data/gemfiles/rails_4.2.gemfile +1 -0
- data/gemfiles/rails_5.0.gemfile +1 -0
- data/lib/aasm/base.rb +8 -0
- data/lib/aasm/core/event.rb +1 -1
- data/lib/aasm/core/transition.rb +1 -1
- data/lib/aasm/instance_base.rb +0 -2
- data/lib/aasm/minitest.rb +5 -0
- data/lib/aasm/minitest/allow_event.rb +13 -0
- data/lib/aasm/minitest/allow_transition_to.rb +13 -0
- data/lib/aasm/minitest/have_state.rb +13 -0
- data/lib/aasm/minitest/transition_from.rb +21 -0
- data/lib/aasm/minitest_spec.rb +15 -0
- data/lib/aasm/persistence/active_record_persistence.rb +25 -101
- data/lib/aasm/persistence/base.rb +7 -3
- data/lib/aasm/persistence/mongoid_persistence.rb +15 -60
- data/lib/aasm/persistence/orm.rb +142 -0
- data/lib/aasm/persistence/redis_persistence.rb +16 -11
- data/lib/aasm/persistence/sequel_persistence.rb +36 -63
- data/lib/aasm/version.rb +1 -1
- data/lib/generators/active_record/templates/migration.rb +1 -1
- data/lib/generators/active_record/templates/migration_existing.rb +1 -1
- data/lib/motion-aasm.rb +2 -0
- data/spec/models/active_record/complex_active_record_example.rb +5 -1
- data/spec/models/guardian_without_from_specified.rb +18 -0
- data/spec/models/namespaced_multiple_example.rb +14 -0
- data/spec/models/redis/complex_redis_example.rb +40 -0
- data/spec/models/redis/redis_multiple.rb +20 -0
- data/spec/models/redis/redis_simple.rb +20 -0
- data/spec/models/sequel/complex_sequel_example.rb +4 -3
- data/spec/models/sequel/invalid_persistor.rb +52 -0
- data/spec/models/sequel/sequel_multiple.rb +13 -13
- data/spec/models/sequel/sequel_simple.rb +13 -12
- data/spec/models/sequel/silent_persistor.rb +50 -0
- data/spec/models/sequel/transactor.rb +112 -0
- data/spec/models/sequel/validator.rb +93 -0
- data/spec/models/sequel/worker.rb +12 -0
- data/spec/spec_helpers/redis.rb +8 -0
- data/spec/unit/guard_spec.rb +17 -0
- data/spec/unit/guard_without_from_specified_spec.rb +10 -0
- data/spec/unit/namespaced_multiple_example_spec.rb +22 -0
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +4 -4
- data/spec/unit/persistence/active_record_persistence_spec.rb +4 -4
- data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
- data/spec/unit/persistence/redis_persistence_spec.rb +5 -25
- data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +2 -2
- data/spec/unit/persistence/sequel_persistence_spec.rb +275 -2
- data/test/minitest_helper.rb +57 -0
- data/test/unit/minitest_matcher_test.rb +80 -0
- metadata +35 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51fca1a6911cbe2585301606192b2d0a467ae7e7
|
4
|
+
data.tar.gz: c4bdfee904a029cec8329eb024c608f225a3b746
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ce9707a179a75f5e75c038ae8102956503564bca475151a6c64dfad9862b313382fc6b7f3ddc2c8e928dfbb666667b171be5abc7bf7d569e5e72cd4ee59467e
|
7
|
+
data.tar.gz: e2c030b9c239c3ced525745ed32f192712ed946fff5f5ed45c8c2710fe3da2aa8291f41faf351b9241c1eb7e6ecf4bb4ad72aace93aeb6f91e0b8af58d253f73
|
data/.travis.yml
CHANGED
@@ -22,10 +22,14 @@ gemfile:
|
|
22
22
|
|
23
23
|
before_script:
|
24
24
|
- mkdir /tmp/dynamodb
|
25
|
-
- wget -O -
|
25
|
+
- wget -O - https://s3-ap-southeast-1.amazonaws.com/dynamodb-local-singapore/dynamodb_local_latest.tar.gz | tar xz --directory /tmp/dynamodb
|
26
26
|
- java -Djava.library.path=/tmp/dynamodb/DynamoDBLocal_lib -jar /tmp/dynamodb/DynamoDBLocal.jar -inMemory -delayTransientStatuses -port 30180 &
|
27
27
|
- mongod --version
|
28
28
|
|
29
|
+
script:
|
30
|
+
- bundle exec rspec spec
|
31
|
+
- bundle exec rake test
|
32
|
+
|
29
33
|
matrix:
|
30
34
|
exclude:
|
31
35
|
- rvm: 1.9.3
|
data/Appraisals
CHANGED
@@ -24,6 +24,7 @@ appraise 'rails_4.2' do
|
|
24
24
|
gem 'sequel'
|
25
25
|
gem 'dynamoid', '~> 1', :platforms => :ruby
|
26
26
|
gem 'aws-sdk', '~>2', :platforms => :ruby
|
27
|
+
gem 'redis-objects'
|
27
28
|
end
|
28
29
|
|
29
30
|
appraise 'rails_4.2_mongoid_5' do
|
@@ -41,4 +42,5 @@ appraise 'rails_5.0' do
|
|
41
42
|
# gem 'dynamoid', '~> 1', :platforms => :ruby
|
42
43
|
|
43
44
|
gem 'aws-sdk', '~>2', :platforms => :ruby
|
45
|
+
gem 'redis-objects'
|
44
46
|
end
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## 4.12.1
|
6
|
+
|
7
|
+
* DRY-up Mongoid and ActiveRecord Persistence, Add Sequel transactions and locking #475, thanks to [@Aryk] (https://github.com/Aryk)
|
8
|
+
* Add aliases for event methods #476, thanks to [@Aryk] (https://github.com/Aryk)
|
9
|
+
* Support Minitest spec expectations (#387), thanks to [@faragorn] (https://github.com/faragorn)
|
5
10
|
## 4.12.0
|
6
11
|
|
7
12
|
* Fix thread safe issue with concurrent-ruby gem [see [pull-request #422](https://github.com/aasm/aasm/pull/442), thanks to [@reidmorrison](https://github.com/reidmorrison)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -210,6 +210,14 @@ Note that when passing arguments to a state transition, the first argument must
|
|
210
210
|
In case of an error during the event processing the error is rescued and passed to `:error`
|
211
211
|
callback, which can handle it or re-raise it for further propagation.
|
212
212
|
|
213
|
+
Also, you can define a method that will be called if any event fails:
|
214
|
+
|
215
|
+
```
|
216
|
+
def aasm_event_failed(event_name, old_state_name)
|
217
|
+
# use custom exception/messages, report metrics, etc
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
213
221
|
During the transition's `:after` callback (and reliably only then, or in the global
|
214
222
|
`after_all_transitions` callback) you can access the originating state (the from-state)
|
215
223
|
and the target state (the to state), like this:
|
@@ -456,9 +464,6 @@ example.aasm(:work).current_state #=> :processing
|
|
456
464
|
example.aasm(:question).current_state #=> :asked
|
457
465
|
```
|
458
466
|
|
459
|
-
*Final note*: Support for multiple state machines per class is a pretty new feature
|
460
|
-
(since version `4.3`), so please bear with us in case it doesn't work as expected.
|
461
|
-
|
462
467
|
### Auto-generated Status Constants
|
463
468
|
|
464
469
|
AASM automatically [generates constants](https://github.com/aasm/aasm/pull/60)
|
@@ -715,8 +720,10 @@ end
|
|
715
720
|
|
716
721
|
### Redis
|
717
722
|
|
718
|
-
AASM also supports persistence in Redis
|
719
|
-
|
723
|
+
AASM also supports persistence in Redis via
|
724
|
+
[Redis::Objects](https://github.com/nateware/redis-objects).
|
725
|
+
Make sure to include Redis::Objects before you include AASM. Note that non-bang
|
726
|
+
events will work as bang events, persisting the changes on every call.
|
720
727
|
|
721
728
|
```ruby
|
722
729
|
class User
|
@@ -896,6 +903,9 @@ class Job < ActiveRecord::Base
|
|
896
903
|
...
|
897
904
|
end
|
898
905
|
|
906
|
+
aasm :another_state_machine, column: 'second_state' do
|
907
|
+
...
|
908
|
+
end
|
899
909
|
end
|
900
910
|
```
|
901
911
|
|
@@ -1006,8 +1016,6 @@ class Job
|
|
1006
1016
|
end
|
1007
1017
|
```
|
1008
1018
|
|
1009
|
-
Be aware though, that this is not yet released. It will be part of _AASM_ version `4.11.0`.
|
1010
|
-
|
1011
1019
|
### RubyMotion support
|
1012
1020
|
|
1013
1021
|
Now supports [CodeDataQuery](https://github.com/infinitered/cdq.git) !
|
@@ -1022,7 +1030,9 @@ the 'instance method symbol / string' way whenever possible when defining guardi
|
|
1022
1030
|
|
1023
1031
|
### Testing
|
1024
1032
|
|
1025
|
-
|
1033
|
+
#### RSpec
|
1034
|
+
|
1035
|
+
AASM provides some matchers for [RSpec](http://rspec.info): `transition_from`, `have_state`, `allow_event` and `allow_transition_to`. Add `require 'aasm/rspec'` to your `spec_helper.rb` file and use them like this:
|
1026
1036
|
|
1027
1037
|
```ruby
|
1028
1038
|
# classes with only the default state machine
|
@@ -1058,6 +1068,90 @@ expect(multiple).to allow_transition_to(:processing).on(:move)
|
|
1058
1068
|
expect(multiple).to_not allow_transition_to(:sleeping).on(:move)
|
1059
1069
|
```
|
1060
1070
|
|
1071
|
+
#### Minitest
|
1072
|
+
|
1073
|
+
AASM provides assertions and rspec-like expectations for [Minitest](https://github.com/seattlerb/minitest).
|
1074
|
+
|
1075
|
+
##### Assertions
|
1076
|
+
|
1077
|
+
List of supported assertions: `assert_have_state`, `refute_have_state`, `assert_transitions_from`, `refute_transitions_from`, `assert_event_allowed`, `refute_event_allowed`, `assert_transition_to_allowed`, `refute_transition_to_allowed`.
|
1078
|
+
|
1079
|
+
Add `require 'aasm/minitest' to your `test_helper.rb` file and use them like this:
|
1080
|
+
|
1081
|
+
```ruby
|
1082
|
+
# classes with only the default state machine
|
1083
|
+
job = Job.new
|
1084
|
+
assert_transitions_from job, :sleeping, to: :running, on_event: :run
|
1085
|
+
refute_transitions_from job, :sleeping, to: :cleaning, on_event: :run
|
1086
|
+
assert_have_state job, :sleeping
|
1087
|
+
refute_have_state job, :running
|
1088
|
+
assert_event_allowed job, :run
|
1089
|
+
refute_event_allowed job, :clean
|
1090
|
+
assert_transition_to_allowed job, :running
|
1091
|
+
refute_transition_to_allowed job, :cleaning
|
1092
|
+
# on_event also accept arguments
|
1093
|
+
assert_transitions_from job, :sleeping, :defragmentation, to: :running, on_event: :run
|
1094
|
+
|
1095
|
+
# classes with multiple state machine
|
1096
|
+
multiple = SimpleMultipleExample.new
|
1097
|
+
assert_transitions_from multiple, :standing, to: :walking, on_event: :walk, on: :move
|
1098
|
+
refute_transitions_from multiple, :standing, to: :running, on_event: :walk, on: :move
|
1099
|
+
assert_have_state multiple, :standing, on: :move
|
1100
|
+
refute_have_state multiple, :walking, on: :move
|
1101
|
+
assert_event_allowed multiple, :walk, on: :move
|
1102
|
+
refute_event_allowed multiple, :hold, on: :move
|
1103
|
+
assert_transition_to_allowed multiple, :walking, on: :move
|
1104
|
+
refute_transition_to_allowed multiple, :running, on: :move
|
1105
|
+
assert_transitions_from multiple, :sleeping, to: :processing, on_event: :start, on: :work
|
1106
|
+
refute_transitions_from multiple, :sleeping, to: :sleeping, on_event: :start, on: :work
|
1107
|
+
assert_have_state multiple, :sleeping, on: :work
|
1108
|
+
refute_have_state multiple, :processing, on: :work
|
1109
|
+
assert_event_allowed multiple, :start, on: :move
|
1110
|
+
refute_event_allowed multiple, :stop, on: :move
|
1111
|
+
assert_transition_to_allowed multiple, :processing, on: :move
|
1112
|
+
refute_transition_to_allowed multiple, :sleeping, on: :move
|
1113
|
+
```
|
1114
|
+
|
1115
|
+
##### Expectations
|
1116
|
+
|
1117
|
+
List of supported expectations: `must_transition_from`, `wont_transition_from`, `must_have_state`, `wont_have_state`, `must_allow_event`, `wont_allow_event`, `must_allow_transition_to`, `wont_allow_transition_to`.
|
1118
|
+
|
1119
|
+
Add `require 'aasm/minitest_spec'` to your `test_helper.rb` file and use them like this:
|
1120
|
+
|
1121
|
+
```ruby
|
1122
|
+
# classes with only the default state machine
|
1123
|
+
job = Job.new
|
1124
|
+
job.must_transition_from :sleeping, to: :running, on_event: :run
|
1125
|
+
job.wont_transition_from :sleeping, to: :cleaning, on_event: :run
|
1126
|
+
job.must_have_state :sleeping
|
1127
|
+
job.wont_have_state :running
|
1128
|
+
job.must_allow_event :run
|
1129
|
+
job.wont_allow_event :clean
|
1130
|
+
job.must_allow_transition_to :running
|
1131
|
+
job.wont_allow_transition_to :cleaning
|
1132
|
+
# on_event also accept arguments
|
1133
|
+
job.must_transition_from :sleeping, :defragmentation, to: :running, on_event: :run
|
1134
|
+
|
1135
|
+
# classes with multiple state machine
|
1136
|
+
multiple = SimpleMultipleExample.new
|
1137
|
+
multiple.must_transition_from :standing, to: :walking, on_event: :walk, on: :move
|
1138
|
+
multiple.wont_transition_from :standing, to: :running, on_event: :walk, on: :move
|
1139
|
+
multiple.must_have_state :standing, on: :move
|
1140
|
+
multiple.wont_have_state :walking, on: :move
|
1141
|
+
multiple.must_allow_event :walk, on: :move
|
1142
|
+
multiple.wont_allow_event :hold, on: :move
|
1143
|
+
multiple.must_allow_transition_to :walking, on: :move
|
1144
|
+
multiple.wont_allow_transition_to :running, on: :move
|
1145
|
+
multiple.must_transition_from :sleeping, to: :processing, on_event: :start, on: :work
|
1146
|
+
multiple.wont_transition_from :sleeping, to: :sleeping, on_event: :start, on: :work
|
1147
|
+
multiple.must_have_state :sleeping, on: :work
|
1148
|
+
multiple.wont_have_state :processing, on: :work
|
1149
|
+
multiple.must_allow_event :start, on: :move
|
1150
|
+
multiple.wont_allow_event :stop, on: :move
|
1151
|
+
multiple.must_allow_transition_to :processing, on: :move
|
1152
|
+
multiple.wont_allow_transition_to :sleeping, on: :move
|
1153
|
+
```
|
1154
|
+
|
1061
1155
|
## <a id="installation">Installation ##
|
1062
1156
|
|
1063
1157
|
### Manually from RubyGems.org ###
|
data/gemfiles/rails_4.2.gemfile
CHANGED
data/gemfiles/rails_5.0.gemfile
CHANGED
data/lib/aasm/base.rb
CHANGED
@@ -130,6 +130,14 @@ module AASM
|
|
130
130
|
aasm(aasm_name).current_event = event
|
131
131
|
aasm_fire_event(aasm_name, event, {:persist => false}, *args, &block)
|
132
132
|
end
|
133
|
+
|
134
|
+
# Create aliases for the event methods. Keep the old names to maintain backwards compatibility.
|
135
|
+
if namespace?
|
136
|
+
klass.send(:alias_method, "may_#{name}_#{namespace}?", "may_#{name}?")
|
137
|
+
klass.send(:alias_method, "#{name}_#{namespace}!", "#{name}!")
|
138
|
+
klass.send(:alias_method, "#{name}_#{namespace}", name)
|
139
|
+
end
|
140
|
+
|
133
141
|
end
|
134
142
|
|
135
143
|
def after_all_transitions(*callbacks, &block)
|
data/lib/aasm/core/event.rb
CHANGED
@@ -96,7 +96,7 @@ module AASM::Core
|
|
96
96
|
@transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
|
97
97
|
end
|
98
98
|
# Create a transition if :to is specified without :from (transitions from ANY state)
|
99
|
-
if
|
99
|
+
if !definitions[:from] && definitions[:to]
|
100
100
|
@transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions), &block)
|
101
101
|
end
|
102
102
|
end
|
data/lib/aasm/core/transition.rb
CHANGED
@@ -69,7 +69,7 @@ module AASM::Core
|
|
69
69
|
|
70
70
|
case code
|
71
71
|
when Symbol, String
|
72
|
-
result = (record.__send__(:method, code.to_sym).arity
|
72
|
+
result = (record.__send__(:method, code.to_sym).arity != 0 ? record.__send__(code, *args) : record.__send__(code))
|
73
73
|
failures << code unless result
|
74
74
|
result
|
75
75
|
when Proc
|
data/lib/aasm/instance_base.rb
CHANGED
@@ -14,7 +14,6 @@ module AASM
|
|
14
14
|
|
15
15
|
def current_state=(state)
|
16
16
|
@instance.aasm_write_state_without_persistence(state, @name)
|
17
|
-
# @current_state = state
|
18
17
|
end
|
19
18
|
|
20
19
|
def enter_initial_state
|
@@ -22,7 +21,6 @@ module AASM
|
|
22
21
|
state_object = state_object_for_name(state_name)
|
23
22
|
|
24
23
|
state_object.fire_callbacks(:before_enter, @instance)
|
25
|
-
# state_object.fire_callbacks(:enter, @instance)
|
26
24
|
self.current_state = state_name
|
27
25
|
state_object.fire_callbacks(:after_enter, @instance)
|
28
26
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Minitest::Assertions
|
2
|
+
def assert_event_allowed(object, event, options = {})
|
3
|
+
state_machine_name = options.fetch(:on, :default)
|
4
|
+
assert object.aasm(state_machine_name).may_fire_event?(event),
|
5
|
+
"Expected that the event :#{event} would be allowed (on :#{state_machine_name})"
|
6
|
+
end
|
7
|
+
|
8
|
+
def refute_event_allowed(object, event, options = {})
|
9
|
+
state_machine_name = options.fetch(:on, :default)
|
10
|
+
refute object.aasm(state_machine_name).may_fire_event?(event),
|
11
|
+
"Expected that the event :#{event} would not be allowed (on :#{state_machine_name})"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Minitest::Assertions
|
2
|
+
def assert_transition_to_allowed(object, to_state, options = {})
|
3
|
+
state_machine_name = options.fetch(:on, :default)
|
4
|
+
assert object.aasm(state_machine_name).states(permitted: true).include?(to_state),
|
5
|
+
"Expected that the state :#{to_state} would be reachable (on :#{state_machine_name})"
|
6
|
+
end
|
7
|
+
|
8
|
+
def refute_transition_to_allowed(object, to_state, options = {})
|
9
|
+
state_machine_name = options.fetch(:on, :default)
|
10
|
+
refute object.aasm(state_machine_name).states(permitted: true).include?(to_state),
|
11
|
+
"Expected that the state :#{to_state} would be reachable (on :#{state_machine_name})"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Minitest::Assertions
|
2
|
+
def assert_have_state(object, state, options = {})
|
3
|
+
state_machine_name = options.fetch(:on, :default)
|
4
|
+
assert object.aasm(state_machine_name).current_state == state,
|
5
|
+
"Expected that :#{object.aasm(state_machine_name).current_state} would be :#{state} (on :#{state_machine_name})"
|
6
|
+
end
|
7
|
+
|
8
|
+
def refute_have_state(object, state, options = {})
|
9
|
+
state_machine_name = options.fetch(:on, :default)
|
10
|
+
refute object.aasm(state_machine_name).current_state == state,
|
11
|
+
"Expected that :#{object.aasm(state_machine_name).current_state} would be :#{state} (on :#{state_machine_name})"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Minitest::Assertions
|
2
|
+
def assert_transitions_from(object, from_state, *args)
|
3
|
+
options = args.first
|
4
|
+
options[:on] ||= :default
|
5
|
+
assert _transitions_from?(object, from_state, args, options),
|
6
|
+
"Expected transition state to :#{options[:to]} from :#{from_state} on event :#{options[:on_event]}, (on :#{options[:on]})"
|
7
|
+
end
|
8
|
+
|
9
|
+
def refute_transitions_from(object, from_state, *args)
|
10
|
+
options = args.first
|
11
|
+
options[:on] ||= :default
|
12
|
+
refute _transitions_from?(object, from_state, args, options),
|
13
|
+
"Expected transition state to :#{options[:to]} from :#{from_state} on event :#{options[:on_event]}, (on :#{options[:on]})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def _transitions_from?(object, from_state, args, options)
|
17
|
+
state_machine_name = options[:on]
|
18
|
+
object.aasm(state_machine_name).current_state = from_state.to_sym
|
19
|
+
object.send(options[:on_event], *args) && options[:to].to_sym == object.aasm(state_machine_name).current_state
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'aasm/minitest'
|
2
|
+
|
3
|
+
module Minitest::Expectations
|
4
|
+
AASM.infect_an_assertion :assert_transitions_from, :must_transition_from, :do_not_flip
|
5
|
+
AASM.infect_an_assertion :refute_transitions_from, :wont_transition_from, :do_not_flip
|
6
|
+
|
7
|
+
AASM.infect_an_assertion :assert_transition_to_allowed, :must_allow_transition_to, :do_not_flip
|
8
|
+
AASM.infect_an_assertion :refute_transition_to_allowed, :wont_allow_transition_to, :do_not_flip
|
9
|
+
|
10
|
+
AASM.infect_an_assertion :assert_have_state, :must_have_state, :do_not_flip
|
11
|
+
AASM.infect_an_assertion :refute_have_state, :wont_have_state, :do_not_flip
|
12
|
+
|
13
|
+
AASM.infect_an_assertion :assert_event_allowed, :must_allow_event, :do_not_flip
|
14
|
+
AASM.infect_an_assertion :refute_event_allowed, :wont_allow_event, :do_not_flip
|
15
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'aasm/persistence/orm'
|
1
2
|
module AASM
|
2
3
|
module Persistence
|
3
4
|
module ActiveRecordPersistence
|
@@ -28,6 +29,7 @@ module AASM
|
|
28
29
|
#
|
29
30
|
def self.included(base)
|
30
31
|
base.send(:include, AASM::Persistence::Base)
|
32
|
+
base.send(:include, AASM::Persistence::ORM)
|
31
33
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
32
34
|
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
|
33
35
|
|
@@ -56,67 +58,41 @@ module AASM
|
|
56
58
|
|
57
59
|
module InstanceMethods
|
58
60
|
|
59
|
-
|
60
|
-
#
|
61
|
-
# foo = Foo.find(1)
|
62
|
-
# foo.aasm.current_state # => :opened
|
63
|
-
# foo.close!
|
64
|
-
# foo.aasm.current_state # => :closed
|
65
|
-
# Foo.find(1).aasm.current_state # => :closed
|
66
|
-
#
|
67
|
-
# NOTE: intended to be called from an event
|
68
|
-
def aasm_write_state(state, name=:default)
|
69
|
-
old_value = read_attribute(self.class.aasm(name).attribute_name)
|
70
|
-
aasm_write_attribute state, name
|
71
|
-
|
72
|
-
success = if aasm_skipping_validations(name)
|
73
|
-
value = aasm_raw_attribute_value(state, name)
|
74
|
-
aasm_update_column(name, value)
|
75
|
-
else
|
76
|
-
self.save
|
77
|
-
end
|
61
|
+
private
|
78
62
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
63
|
+
def aasm_raise_invalid_record
|
64
|
+
raise ActiveRecord::RecordInvalid.new(self)
|
65
|
+
end
|
83
66
|
|
84
|
-
|
67
|
+
def aasm_save
|
68
|
+
self.save
|
85
69
|
end
|
86
70
|
|
87
|
-
|
88
|
-
|
89
|
-
# foo = Foo.find(1)
|
90
|
-
# foo.aasm.current_state # => :opened
|
91
|
-
# foo.close
|
92
|
-
# foo.aasm.current_state # => :closed
|
93
|
-
# Foo.find(1).aasm.current_state # => :opened
|
94
|
-
# foo.save
|
95
|
-
# foo.aasm.current_state # => :closed
|
96
|
-
# Foo.find(1).aasm.current_state # => :closed
|
97
|
-
#
|
98
|
-
# NOTE: intended to be called from an event
|
99
|
-
def aasm_write_state_without_persistence(state, name=:default)
|
100
|
-
aasm_write_attribute(state, name)
|
71
|
+
def aasm_update_column(attribute_name, value)
|
72
|
+
self.class.unscoped.where(self.class.primary_key => self.id).update_all(attribute_name => value) == 1
|
101
73
|
end
|
102
74
|
|
103
|
-
|
75
|
+
def aasm_read_attribute(name)
|
76
|
+
read_attribute(name)
|
77
|
+
end
|
104
78
|
|
105
|
-
def
|
106
|
-
|
79
|
+
def aasm_write_attribute(name, value)
|
80
|
+
write_attribute(name, value)
|
107
81
|
end
|
108
82
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
83
|
+
def aasm_transaction(requires_new, requires_lock)
|
84
|
+
self.class.transaction(:requires_new => requires_new) do
|
85
|
+
lock!(requires_lock) if requires_lock
|
86
|
+
yield
|
87
|
+
end
|
112
88
|
end
|
113
89
|
|
114
90
|
def aasm_enum(name=:default)
|
115
91
|
case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
92
|
+
when false then nil
|
93
|
+
when true then aasm_guess_enum_method(name)
|
94
|
+
when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
|
95
|
+
else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
120
96
|
end
|
121
97
|
end
|
122
98
|
|
@@ -131,23 +107,11 @@ module AASM
|
|
131
107
|
self.class.aasm(name).attribute_name.to_s.pluralize.to_sym
|
132
108
|
end
|
133
109
|
|
134
|
-
def aasm_skipping_validations(state_machine_name)
|
135
|
-
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
|
136
|
-
end
|
137
|
-
|
138
|
-
def aasm_whiny_persistence(state_machine_name)
|
139
|
-
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.whiny_persistence
|
140
|
-
end
|
141
|
-
|
142
|
-
def aasm_write_attribute(state, name=:default)
|
143
|
-
write_attribute(self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name))
|
144
|
-
end
|
145
|
-
|
146
110
|
def aasm_raw_attribute_value(state, name=:default)
|
147
111
|
if aasm_enum(name)
|
148
112
|
self.class.send(aasm_enum(name))[state]
|
149
113
|
else
|
150
|
-
|
114
|
+
super
|
151
115
|
end
|
152
116
|
end
|
153
117
|
|
@@ -179,46 +143,6 @@ module AASM
|
|
179
143
|
attribute_names.include?(attribute_name.to_s) && send(attribute_name).blank?
|
180
144
|
end
|
181
145
|
|
182
|
-
def aasm_fire_event(state_machine_name, name, options, *args, &block)
|
183
|
-
event = self.class.aasm(state_machine_name).state_machine.events[name]
|
184
|
-
|
185
|
-
if options[:persist]
|
186
|
-
event.fire_callbacks(:before_transaction, self, *args)
|
187
|
-
event.fire_global_callbacks(:before_all_transactions, self, *args)
|
188
|
-
end
|
189
|
-
|
190
|
-
begin
|
191
|
-
success = if options[:persist]
|
192
|
-
self.class.transaction(:requires_new => requires_new?(state_machine_name)) do
|
193
|
-
lock!(requires_lock?(state_machine_name)) if requires_lock?(state_machine_name)
|
194
|
-
super
|
195
|
-
end
|
196
|
-
else
|
197
|
-
super
|
198
|
-
end
|
199
|
-
|
200
|
-
if options[:persist] && success
|
201
|
-
event.fire_callbacks(:after_commit, self, *args)
|
202
|
-
event.fire_global_callbacks(:after_all_commits, self, *args)
|
203
|
-
end
|
204
|
-
ensure
|
205
|
-
if options[:persist]
|
206
|
-
event.fire_callbacks(:after_transaction, self, *args)
|
207
|
-
event.fire_global_callbacks(:after_all_transactions, self, *args)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
success
|
212
|
-
end
|
213
|
-
|
214
|
-
def requires_new?(state_machine_name)
|
215
|
-
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_new_transaction
|
216
|
-
end
|
217
|
-
|
218
|
-
def requires_lock?(state_machine_name)
|
219
|
-
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_lock
|
220
|
-
end
|
221
|
-
|
222
146
|
def aasm_validate_states
|
223
147
|
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
224
148
|
unless aasm_skipping_validations(state_machine_name)
|