statesman 8.0.3 → 10.0.0
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/.circleci/config.yml +100 -130
- data/.github/dependabot.yml +7 -0
- data/.gitignore +68 -15
- data/.rubocop.yml +10 -1
- data/.rubocop_todo.yml +37 -28
- data/.ruby-version +1 -0
- data/CHANGELOG.md +23 -2
- data/CONTRIBUTING.md +18 -0
- data/Gemfile +0 -3
- data/README.md +47 -1
- data/lib/statesman/adapters/active_record.rb +13 -1
- data/lib/statesman/exceptions.rb +4 -0
- data/lib/statesman/machine.rb +52 -0
- data/lib/statesman/version.rb +1 -1
- data/spec/statesman/adapters/active_record_queries_spec.rb +3 -4
- data/spec/statesman/adapters/shared_examples.rb +1 -0
- data/spec/statesman/exceptions_spec.rb +9 -0
- data/spec/statesman/machine_spec.rb +145 -5
- data/spec/support/active_record.rb +6 -6
- data/statesman.gemspec +4 -4
- metadata +16 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 172b3bbeecd2cbd2df8fc9a5485c548c0d729cf0994fda1771d25c8e44f41877
|
|
4
|
+
data.tar.gz: 3556cc13e2433e920ce9bd275bce155a095f6a0e64547a5ff003e0f5fa4dfc74
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21f91dd2537c3e5e480dc0f5adb592ebbeaef9974cfbede1d94aa8b6946c26e9394199029e0281372a2ec4452e1173cb5cba86f0bf1507de19677c398df20350
|
|
7
|
+
data.tar.gz: 58ee880508df011be1caea1f85a475760cf79e07c1ad60f241f4ef4146983997560f17fe1d3a93f5856c6e519831d71eae6c4bd8f7e70f6d0d4ce49253f1ac3f
|
data/.circleci/config.yml
CHANGED
|
@@ -1,157 +1,127 @@
|
|
|
1
1
|
---
|
|
2
|
-
version: 2
|
|
2
|
+
version: 2.1
|
|
3
3
|
|
|
4
4
|
references:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- run: gem install bundler -v 2.1.4
|
|
5
|
+
bundle_install: &bundle_install
|
|
6
|
+
run:
|
|
7
|
+
name: Bundle
|
|
8
|
+
command: |
|
|
9
|
+
gem install bundler --no-document && \
|
|
10
|
+
bundle config set no-cache 'true' && \
|
|
11
|
+
bundle config set jobs '4' && \
|
|
12
|
+
bundle config set retry '3' && \
|
|
13
|
+
bundle install
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
key: statesman-{{ checksum "Gemfile" }}-{{ checksum "~/RAILS_VERSION.txt" }}
|
|
15
|
+
cache_bundle: &cache_bundle
|
|
16
|
+
save_cache:
|
|
17
|
+
key: bundle-<< parameters.ruby_version >>-<< parameters.rails_version >>-{{ checksum "statesman.gemspec" }}-{{ checksum "Gemfile" }}
|
|
21
18
|
paths:
|
|
22
19
|
- vendor/bundle
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
restore_bundle: &restore_bundle
|
|
22
|
+
restore_cache:
|
|
23
|
+
key: bundle-<< parameters.ruby_version >>-<< parameters.rails_version >>-{{ checksum "statesman.gemspec" }}-{{ checksum "Gemfile" }}
|
|
25
24
|
|
|
25
|
+
steps: &steps
|
|
26
|
+
- add_ssh_keys
|
|
27
|
+
- checkout
|
|
28
|
+
- run:
|
|
29
|
+
name: "Add dependencies"
|
|
30
|
+
command: |
|
|
31
|
+
sudo apt-get update && sudo apt-get install -y sqlite3 libsqlite3-dev
|
|
32
|
+
- *restore_bundle
|
|
33
|
+
- *bundle_install
|
|
34
|
+
- *cache_bundle
|
|
26
35
|
- run: dockerize -wait tcp://localhost:$DATABASE_DEPENDENCY_PORT -timeout 1m
|
|
36
|
+
- run:
|
|
37
|
+
name: Run specs
|
|
38
|
+
command: |
|
|
39
|
+
bundle exec rspec $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) --profile --format progress --format RspecJunitFormatter -o /tmp/circle_artifacts/rspec.xml
|
|
40
|
+
- run:
|
|
41
|
+
name: "Rubocop"
|
|
42
|
+
command: bundle exec rubocop --extra-details --display-style-guide --parallel --force-exclusion
|
|
43
|
+
- store_artifacts:
|
|
44
|
+
path: /tmp/circle_artifacts/
|
|
45
|
+
- store_test_results:
|
|
46
|
+
path: /tmp/circle_artifacts/
|
|
27
47
|
|
|
28
|
-
|
|
48
|
+
ruby_versions: &ruby_versions
|
|
49
|
+
- "2.7"
|
|
50
|
+
- "3.0"
|
|
51
|
+
- "3.1"
|
|
29
52
|
|
|
30
|
-
|
|
31
|
-
|
|
53
|
+
rails_versions: &rails_versions
|
|
54
|
+
- "5.2.7"
|
|
55
|
+
- "6.0.4"
|
|
56
|
+
- "6.1.5"
|
|
57
|
+
- "7.0.2"
|
|
58
|
+
- "main"
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
docker:
|
|
36
|
-
- image: circleci/ruby:2.4.9-node
|
|
37
|
-
environment:
|
|
38
|
-
- RAILS_VERSION=5.2.4
|
|
39
|
-
- DATABASE_URL=mysql2://root@127.0.0.1/statesman_test
|
|
40
|
-
- DATABASE_DEPENDENCY_PORT=3306
|
|
41
|
-
- image: circleci/mysql:5.7.18
|
|
42
|
-
environment:
|
|
43
|
-
- MYSQL_ALLOW_EMPTY_PASSWORD=true
|
|
44
|
-
- MYSQL_USER=root
|
|
45
|
-
- MYSQL_PASSWORD=
|
|
46
|
-
- MYSQL_DATABASE=statesman_test
|
|
47
|
-
steps: *steps
|
|
48
|
-
build-ruby249-rails-524-postgres:
|
|
49
|
-
docker:
|
|
50
|
-
- image: circleci/ruby:2.4.9-node
|
|
51
|
-
environment:
|
|
52
|
-
- RAILS_VERSION=5.2.4
|
|
53
|
-
- DATABASE_URL=postgres://postgres@localhost/statesman_test
|
|
54
|
-
- DATABASE_DEPENDENCY_PORT=5432
|
|
55
|
-
- image: circleci/postgres:9.6
|
|
56
|
-
environment:
|
|
57
|
-
- POSTGRES_USER=postgres
|
|
58
|
-
- POSTGRES_DB=statesman_test
|
|
59
|
-
- POSTGRES_PASSWORD=statesman
|
|
60
|
-
steps: *steps
|
|
60
|
+
mysql_versions: &mysql_versions
|
|
61
|
+
- "5.7"
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- image: circleci/ruby:2.6.5-node
|
|
65
|
-
environment:
|
|
66
|
-
- RAILS_VERSION=6.0.2
|
|
67
|
-
- DATABASE_URL=mysql2://root@127.0.0.1/statesman_test
|
|
68
|
-
- DATABASE_DEPENDENCY_PORT=3306
|
|
69
|
-
- image: circleci/mysql:5.7.18
|
|
70
|
-
environment:
|
|
71
|
-
- MYSQL_ALLOW_EMPTY_PASSWORD=true
|
|
72
|
-
- MYSQL_USER=root
|
|
73
|
-
- MYSQL_PASSWORD=
|
|
74
|
-
- MYSQL_DATABASE=statesman_test
|
|
75
|
-
steps: *steps
|
|
76
|
-
build-ruby265-rails-602-postgres:
|
|
77
|
-
docker:
|
|
78
|
-
- image: circleci/ruby:2.6.5-node
|
|
79
|
-
environment:
|
|
80
|
-
- RAILS_VERSION=6.0.2
|
|
81
|
-
- DATABASE_URL=postgres://postgres@localhost/statesman_test
|
|
82
|
-
- DATABASE_DEPENDENCY_PORT=5432
|
|
83
|
-
- image: circleci/postgres:9.6
|
|
84
|
-
environment:
|
|
85
|
-
- POSTGRES_USER=postgres
|
|
86
|
-
- POSTGRES_DB=statesman_test
|
|
87
|
-
- POSTGRES_PASSWORD=statesman
|
|
88
|
-
steps: *steps
|
|
63
|
+
psql_versions: &psql_versions
|
|
64
|
+
- "9.6"
|
|
89
65
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- MYSQL_USER=root
|
|
101
|
-
- MYSQL_PASSWORD=
|
|
102
|
-
- MYSQL_DATABASE=statesman_test
|
|
103
|
-
steps: *steps
|
|
104
|
-
build-ruby270-rails-602-postgres:
|
|
105
|
-
docker:
|
|
106
|
-
- image: circleci/ruby:2.7.0-node
|
|
107
|
-
environment:
|
|
108
|
-
- RAILS_VERSION=6.0.2
|
|
109
|
-
- DATABASE_URL=postgres://postgres@localhost/statesman_test
|
|
110
|
-
- DATABASE_DEPENDENCY_PORT=5432
|
|
111
|
-
- image: circleci/postgres:9.6
|
|
112
|
-
environment:
|
|
113
|
-
- POSTGRES_USER=postgres
|
|
114
|
-
- POSTGRES_DB=statesman_test
|
|
115
|
-
- POSTGRES_PASSWORD=statesman
|
|
116
|
-
steps: *steps
|
|
117
|
-
build-ruby270-rails-main-mysql:
|
|
66
|
+
jobs:
|
|
67
|
+
rspec_mysql:
|
|
68
|
+
working_directory: /mnt/ramdisk
|
|
69
|
+
parameters:
|
|
70
|
+
ruby_version:
|
|
71
|
+
type: string
|
|
72
|
+
rails_version:
|
|
73
|
+
type: string
|
|
74
|
+
mysql_version:
|
|
75
|
+
type: string
|
|
118
76
|
docker:
|
|
119
|
-
- image:
|
|
77
|
+
- image: cimg/ruby:<< parameters.ruby_version >>
|
|
120
78
|
environment:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- image:
|
|
79
|
+
CIRCLE_TEST_REPORTS: /tmp/circle_artifacts/
|
|
80
|
+
DATABASE_URL: mysql2://foobar:password@127.0.0.1/statesman_test
|
|
81
|
+
DATABASE_DEPENDENCY_PORT: "3306"
|
|
82
|
+
- image: cimg/mysql:<< parameters.mysql_version >>
|
|
125
83
|
environment:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
84
|
+
MYSQL_ROOT_PASSWORD: password
|
|
85
|
+
MYSQL_USER: foobar
|
|
86
|
+
MYSQL_PASSWORD: password
|
|
87
|
+
MYSQL_DATABASE: statesman_test
|
|
130
88
|
steps: *steps
|
|
131
|
-
|
|
89
|
+
|
|
90
|
+
rspec_postgres:
|
|
91
|
+
working_directory: /mnt/ramdisk
|
|
92
|
+
parameters:
|
|
93
|
+
ruby_version:
|
|
94
|
+
type: string
|
|
95
|
+
rails_version:
|
|
96
|
+
type: string
|
|
97
|
+
psql_version:
|
|
98
|
+
type: string
|
|
132
99
|
docker:
|
|
133
|
-
- image:
|
|
100
|
+
- image: cimg/ruby:<< parameters.ruby_version >>
|
|
134
101
|
environment:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- image: circleci/postgres:9.6
|
|
102
|
+
CIRCLE_TEST_REPORTS: /tmp/circle_artifacts/
|
|
103
|
+
DATABASE_URL: postgres://postgres@localhost/statesman_test
|
|
104
|
+
DATABASE_DEPENDENCY_PORT: "5432"
|
|
105
|
+
- image: circleci/postgres:<< parameters.psql_version >>
|
|
140
106
|
environment:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
107
|
+
POSTGRES_USER: postgres
|
|
108
|
+
POSTGRES_DB: statesman_test
|
|
109
|
+
POSTGRES_PASSWORD: statesman
|
|
144
110
|
steps: *steps
|
|
145
111
|
|
|
146
112
|
workflows:
|
|
147
113
|
version: 2
|
|
148
114
|
tests:
|
|
149
115
|
jobs:
|
|
150
|
-
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
|
|
116
|
+
- rspec_mysql:
|
|
117
|
+
matrix:
|
|
118
|
+
parameters:
|
|
119
|
+
mysql_version: *mysql_versions
|
|
120
|
+
ruby_version: *ruby_versions
|
|
121
|
+
rails_version: *rails_versions
|
|
122
|
+
- rspec_postgres:
|
|
123
|
+
matrix:
|
|
124
|
+
parameters:
|
|
125
|
+
psql_version: *psql_versions
|
|
126
|
+
ruby_version: *ruby_versions
|
|
127
|
+
rails_version: *rails_versions
|
data/.gitignore
CHANGED
|
@@ -1,18 +1,71 @@
|
|
|
1
1
|
*.gem
|
|
2
2
|
*.rbc
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
/.config
|
|
4
|
+
/coverage/
|
|
5
|
+
/InstalledFiles
|
|
6
|
+
/pkg/
|
|
7
|
+
/spec/reports/
|
|
8
|
+
/spec/examples.txt
|
|
9
|
+
/test/tmp/
|
|
10
|
+
/test/version_tmp/
|
|
11
|
+
/tmp/
|
|
12
|
+
|
|
13
|
+
# Used by dotenv library to load environment variables.
|
|
14
|
+
# .env
|
|
15
|
+
|
|
16
|
+
# Ignore Byebug command history file.
|
|
17
|
+
.byebug_history
|
|
18
|
+
|
|
19
|
+
## Specific to RubyMotion:
|
|
20
|
+
.dat*
|
|
21
|
+
.repl_history
|
|
22
|
+
build/
|
|
23
|
+
*.bridgesupport
|
|
24
|
+
build-iPhoneOS/
|
|
25
|
+
build-iPhoneSimulator/
|
|
26
|
+
|
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
|
28
|
+
#
|
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
|
32
|
+
#
|
|
33
|
+
# vendor/Pods/
|
|
34
|
+
|
|
35
|
+
## Documentation cache and generated files:
|
|
36
|
+
/.yardoc/
|
|
37
|
+
/_yardoc/
|
|
38
|
+
/doc/
|
|
39
|
+
/rdoc/
|
|
40
|
+
|
|
41
|
+
## Environment normalization:
|
|
42
|
+
/.bundle/
|
|
43
|
+
/vendor/bundle
|
|
44
|
+
/lib/bundler/man/
|
|
45
|
+
|
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
7
48
|
Gemfile.lock
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
49
|
+
# .ruby-version
|
|
50
|
+
# .ruby-gemset
|
|
51
|
+
|
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
53
|
+
.rvmrc
|
|
54
|
+
|
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
|
56
|
+
# .rubocop-https?--*
|
|
57
|
+
|
|
58
|
+
# Project-specific ignores
|
|
59
|
+
.rspec
|
|
60
|
+
|
|
61
|
+
# VSCode
|
|
62
|
+
.vscode
|
|
63
|
+
|
|
64
|
+
# Local History for Visual Studio Code
|
|
65
|
+
.history/
|
|
66
|
+
|
|
67
|
+
# Built Visual Studio Code Extensions
|
|
68
|
+
*.vsix
|
|
69
|
+
|
|
70
|
+
# JetBrains
|
|
71
|
+
.idea
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on
|
|
3
|
+
# on 2021-08-09 15:32:40 UTC using RuboCop version 1.18.4.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: Include.
|
|
11
|
+
# Include: **/*.gemspec
|
|
9
12
|
Gemspec/RequiredRubyVersion:
|
|
10
|
-
|
|
13
|
+
Exclude:
|
|
14
|
+
- 'statesman.gemspec'
|
|
15
|
+
|
|
16
|
+
# Offense count: 1
|
|
17
|
+
Lint/MissingSuper:
|
|
18
|
+
Exclude:
|
|
19
|
+
- 'lib/statesman/adapters/active_record_queries.rb'
|
|
11
20
|
|
|
12
21
|
# Offense count: 5
|
|
22
|
+
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
|
|
13
23
|
Metrics/AbcSize:
|
|
14
|
-
Max:
|
|
24
|
+
Max: 20
|
|
25
|
+
|
|
26
|
+
# Offense count: 1
|
|
27
|
+
# Configuration parameters: IgnoredMethods.
|
|
28
|
+
Metrics/CyclomaticComplexity:
|
|
29
|
+
Max: 8
|
|
15
30
|
|
|
16
|
-
# Offense count:
|
|
17
|
-
# Configuration parameters: CountComments, ExcludedMethods.
|
|
31
|
+
# Offense count: 3
|
|
32
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
18
33
|
Metrics/MethodLength:
|
|
19
34
|
Max: 14
|
|
20
35
|
|
|
21
|
-
# Offense count:
|
|
22
|
-
#
|
|
23
|
-
# Configuration parameters: SkipBlocks, EnforcedStyle.
|
|
24
|
-
# SupportedStyles: described_class, explicit
|
|
25
|
-
RSpec/DescribedClass:
|
|
26
|
-
Exclude:
|
|
27
|
-
- 'spec/statesman/adapters/active_record_queries_spec.rb'
|
|
28
|
-
|
|
29
|
-
# Offense count: 7
|
|
30
|
-
# Configuration parameters: Max.
|
|
36
|
+
# Offense count: 11
|
|
37
|
+
# Configuration parameters: CountAsOne.
|
|
31
38
|
RSpec/ExampleLength:
|
|
32
|
-
|
|
33
|
-
- 'spec/statesman/adapters/active_record_spec.rb'
|
|
34
|
-
- 'spec/statesman/adapters/shared_examples.rb'
|
|
35
|
-
- 'spec/statesman/machine_spec.rb'
|
|
39
|
+
Max: 14
|
|
36
40
|
|
|
37
41
|
# Offense count: 7
|
|
38
42
|
RSpec/ExpectInHook:
|
|
@@ -40,11 +44,12 @@ RSpec/ExpectInHook:
|
|
|
40
44
|
- 'spec/statesman/adapters/active_record_spec.rb'
|
|
41
45
|
- 'spec/statesman/machine_spec.rb'
|
|
42
46
|
|
|
43
|
-
# Offense count:
|
|
44
|
-
|
|
47
|
+
# Offense count: 1
|
|
48
|
+
# Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly.
|
|
49
|
+
# Include: **/*_spec*rb*, **/spec/**/*
|
|
50
|
+
RSpec/FilePath:
|
|
45
51
|
Exclude:
|
|
46
|
-
- 'spec/statesman/
|
|
47
|
-
- 'spec/statesman/adapters/shared_examples.rb'
|
|
52
|
+
- 'spec/statesman/exceptions_spec.rb'
|
|
48
53
|
|
|
49
54
|
# Offense count: 1
|
|
50
55
|
# Configuration parameters: AssignmentOnly.
|
|
@@ -75,23 +80,27 @@ RSpec/MessageSpies:
|
|
|
75
80
|
Exclude:
|
|
76
81
|
- 'spec/statesman/callback_spec.rb'
|
|
77
82
|
|
|
78
|
-
# Offense count:
|
|
79
|
-
# Configuration parameters: AggregateFailuresByDefault.
|
|
83
|
+
# Offense count: 14
|
|
80
84
|
RSpec/MultipleExpectations:
|
|
81
85
|
Max: 3
|
|
82
86
|
|
|
83
|
-
# Offense count:
|
|
87
|
+
# Offense count: 49
|
|
84
88
|
RSpec/NestedGroups:
|
|
85
89
|
Max: 6
|
|
86
90
|
|
|
87
|
-
# Offense count:
|
|
91
|
+
# Offense count: 2
|
|
92
|
+
RSpec/RepeatedExampleGroupBody:
|
|
93
|
+
Exclude:
|
|
94
|
+
- 'spec/statesman/exceptions_spec.rb'
|
|
95
|
+
|
|
96
|
+
# Offense count: 12
|
|
88
97
|
RSpec/ScatteredSetup:
|
|
89
98
|
Exclude:
|
|
90
99
|
- 'spec/statesman/adapters/active_record_spec.rb'
|
|
91
100
|
- 'spec/statesman/adapters/shared_examples.rb'
|
|
92
101
|
- 'spec/statesman/machine_spec.rb'
|
|
93
102
|
|
|
94
|
-
# Offense count:
|
|
103
|
+
# Offense count: 7
|
|
95
104
|
# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
|
|
96
105
|
RSpec/VerifiedDoubles:
|
|
97
106
|
Exclude:
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
|
-
##
|
|
1
|
+
## v10.0.0 17th May 2022
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
- Added support for Ruby 3.1 [#462](https://github.com/gocardless/statesman/pull/462)
|
|
5
|
+
- Removed support for Ruby 2.5 and 2.6 [#462](https://github.com/gocardless/statesman/pull/462)
|
|
6
|
+
- Added `remove_state` and `remove_transitions` methods to `Statesman::Machine` [#464](https://github.com/gocardless/statesman/pull/464)
|
|
7
|
+
|
|
8
|
+
## v9.0.1 4th February 2021
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Deprecate `ActiveRecord::Base.default_timezone` in favour of `ActiveRecord.default_timezone` [#446](https://github.com/gocardless/statesman/pull/446)
|
|
12
|
+
|
|
13
|
+
## v9.0.0 9th August 2021
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Added Ruby 3.0 support
|
|
17
|
+
|
|
18
|
+
### Breaking changes
|
|
19
|
+
|
|
20
|
+
- Removed Ruby 2.4
|
|
21
|
+
|
|
22
|
+
## v8.0.3 8th June 2021
|
|
2
23
|
|
|
3
24
|
### Added
|
|
4
25
|
- Implement `Machine#last_transition_to`, to find the last transition to a given state
|
|
5
|
-
[#
|
|
26
|
+
[#438](https://github.com/gocardless/statesman/pull/438)
|
|
6
27
|
|
|
7
28
|
## v8.0.2 30th March 2021
|
|
8
29
|
|
data/CONTRIBUTING.md
CHANGED
|
@@ -19,3 +19,21 @@ request passes by running `rubocop`.
|
|
|
19
19
|
|
|
20
20
|
Please add a section to the readme for any new feature additions or behaviour
|
|
21
21
|
changes.
|
|
22
|
+
|
|
23
|
+
## Releasing
|
|
24
|
+
|
|
25
|
+
We publish new versions of Stateman using [RubyGems](https://guides.rubygems.org/publishing/). Once
|
|
26
|
+
the relevant changes have been merged and `VERSION` has been appropriately bumped to the new
|
|
27
|
+
version, we run the following command.
|
|
28
|
+
```
|
|
29
|
+
$ gem build statesman.gemspec
|
|
30
|
+
```
|
|
31
|
+
This builds a `.gem` file locally that will be named something like `statesman-X` where `X` is the
|
|
32
|
+
new version. For example, if we are releasing version 9.0.0, the file would be
|
|
33
|
+
`statesman-9.0.0.gem`.
|
|
34
|
+
|
|
35
|
+
To publish, run `gem push` with the new `.gem` file we just generated. This requires a OTP that is currently only available
|
|
36
|
+
to GoCardless engineers. For example, if we were to continue to publish version 9.0.0, we would run:
|
|
37
|
+
```
|
|
38
|
+
$ gem push statesman-9.0.0.gem
|
|
39
|
+
```
|
data/Gemfile
CHANGED
|
@@ -4,14 +4,11 @@ source 'https://rubygems.org'
|
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
|
-
# rubocop:disable Bundler/DuplicatedGem
|
|
8
7
|
if ENV['RAILS_VERSION'] == 'main'
|
|
9
8
|
gem "rails", git: "https://github.com/rails/rails", branch: "main"
|
|
10
9
|
elsif ENV['RAILS_VERSION']
|
|
11
10
|
gem "rails", "~> #{ENV['RAILS_VERSION']}"
|
|
12
11
|
end
|
|
13
|
-
# rubocop:enable Bundler/DuplicatedGem
|
|
14
|
-
|
|
15
12
|
group :development do
|
|
16
13
|
# test/unit is no longer bundled with Ruby 2.2, but required by Rails
|
|
17
14
|
gem "test-unit", "~> 3.3" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.2.0")
|
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', '~> 10.0.0'
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
## Usage
|
|
@@ -116,6 +116,52 @@ Order.in_state(:cancelled) # => [#<Order id: "123">]
|
|
|
116
116
|
Order.not_in_state(:checking_out) # => [#<Order id: "123">]
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
If you'd like, you can also define a template for a generic state machine, then alter classes which extend it as required:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
module Template
|
|
123
|
+
def define_states
|
|
124
|
+
state :a, initial: true
|
|
125
|
+
state :b
|
|
126
|
+
state :c
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def define_transitions
|
|
130
|
+
transition from: :a, to: :b
|
|
131
|
+
transition from: :b, to: :c
|
|
132
|
+
transition from: :c, to: :a
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
class Circular
|
|
137
|
+
include Statesman::Machine
|
|
138
|
+
extend Template
|
|
139
|
+
|
|
140
|
+
define_states
|
|
141
|
+
define_transitions
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
class Linear
|
|
145
|
+
include Statesman::Machine
|
|
146
|
+
extend Template
|
|
147
|
+
|
|
148
|
+
define_states
|
|
149
|
+
define_transitions
|
|
150
|
+
|
|
151
|
+
remove_transitions from: :c, to: :a
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
class Shorter
|
|
155
|
+
include Statesman::Machine
|
|
156
|
+
extend Template
|
|
157
|
+
|
|
158
|
+
define_states
|
|
159
|
+
define_transitions
|
|
160
|
+
|
|
161
|
+
remove_state :c
|
|
162
|
+
end
|
|
163
|
+
```
|
|
164
|
+
|
|
119
165
|
## Persistence
|
|
120
166
|
|
|
121
167
|
By default Statesman stores transition history in memory only. It can be
|
|
@@ -65,6 +65,7 @@ module Statesman
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
|
68
69
|
def last(force_reload: false)
|
|
69
70
|
if force_reload
|
|
70
71
|
@last_transition = history(force_reload: true).last
|
|
@@ -72,6 +73,7 @@ module Statesman
|
|
|
72
73
|
@last_transition ||= history.last
|
|
73
74
|
end
|
|
74
75
|
end
|
|
76
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
|
75
77
|
|
|
76
78
|
def reset
|
|
77
79
|
@last_transition = nil
|
|
@@ -302,10 +304,20 @@ module Statesman
|
|
|
302
304
|
return nil if column.nil?
|
|
303
305
|
|
|
304
306
|
[
|
|
305
|
-
column,
|
|
307
|
+
column, default_timezone == :utc ? Time.now.utc : Time.now
|
|
306
308
|
]
|
|
307
309
|
end
|
|
308
310
|
|
|
311
|
+
def default_timezone
|
|
312
|
+
# Rails 7 deprecates ActiveRecord::Base.default_timezone
|
|
313
|
+
# in favour of ActiveRecord.default_timezone
|
|
314
|
+
if ::ActiveRecord.respond_to?(:default_timezone)
|
|
315
|
+
return ::ActiveRecord.default_timezone
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
::ActiveRecord::Base.default_timezone
|
|
319
|
+
end
|
|
320
|
+
|
|
309
321
|
def mysql_gaplock_protection?
|
|
310
322
|
Statesman.mysql_gaplock_protection?
|
|
311
323
|
end
|
data/lib/statesman/exceptions.rb
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
module Statesman
|
|
4
4
|
class InvalidStateError < StandardError; end
|
|
5
|
+
|
|
5
6
|
class InvalidTransitionError < StandardError; end
|
|
7
|
+
|
|
6
8
|
class InvalidCallbackError < StandardError; end
|
|
9
|
+
|
|
7
10
|
class TransitionConflictError < StandardError; end
|
|
11
|
+
|
|
8
12
|
class MissingTransitionAssociation < StandardError; end
|
|
9
13
|
|
|
10
14
|
class TransitionFailedError < StandardError
|
data/lib/statesman/machine.rb
CHANGED
|
@@ -42,6 +42,17 @@ module Statesman
|
|
|
42
42
|
states << name
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
def remove_state(state_name)
|
|
46
|
+
state_name = state_name.to_s
|
|
47
|
+
|
|
48
|
+
remove_transitions(from: state_name)
|
|
49
|
+
remove_transitions(to: state_name)
|
|
50
|
+
remove_callbacks(from: state_name)
|
|
51
|
+
remove_callbacks(to: state_name)
|
|
52
|
+
|
|
53
|
+
@states.delete(state_name.to_s)
|
|
54
|
+
end
|
|
55
|
+
|
|
45
56
|
def successors
|
|
46
57
|
@successors ||= {}
|
|
47
58
|
end
|
|
@@ -70,6 +81,20 @@ module Statesman
|
|
|
70
81
|
successors[from] += to
|
|
71
82
|
end
|
|
72
83
|
|
|
84
|
+
def remove_transitions(from: nil, to: nil)
|
|
85
|
+
raise ArgumentError, "Both from and to can't be nil!" if from.nil? && to.nil?
|
|
86
|
+
return if successors.nil?
|
|
87
|
+
|
|
88
|
+
if from.present?
|
|
89
|
+
@successors[from.to_s].delete(to.to_s) if to.present?
|
|
90
|
+
@successors.delete(from.to_s) if to.nil? || successors[from.to_s].empty?
|
|
91
|
+
elsif to.present?
|
|
92
|
+
@successors.
|
|
93
|
+
transform_values! { |to_states| to_states - [to.to_s] }.
|
|
94
|
+
filter! { |_from_state, to_states| to_states.any? }
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
73
98
|
def before_transition(options = {}, &block)
|
|
74
99
|
add_callback(callback_type: :before, callback_class: Callback,
|
|
75
100
|
from: options[:from], to: options[:to], &block)
|
|
@@ -151,6 +176,33 @@ module Statesman
|
|
|
151
176
|
callback_class.new(from: from, to: to, callback: block)
|
|
152
177
|
end
|
|
153
178
|
|
|
179
|
+
def remove_callbacks(from: nil, to: nil)
|
|
180
|
+
raise ArgumentError, "Both from and to can't be nil!" if from.nil? && to.nil?
|
|
181
|
+
return if callbacks.nil?
|
|
182
|
+
|
|
183
|
+
@callbacks.transform_values! do |callbacks|
|
|
184
|
+
filter_callbacks(callbacks, from: from, to: to)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def filter_callbacks(callbacks, from: nil, to: nil)
|
|
189
|
+
callbacks.filter_map do |callback|
|
|
190
|
+
next if callback.from == from && to.nil?
|
|
191
|
+
|
|
192
|
+
if callback.to.include?(to) && (from.nil? || callback.from == from)
|
|
193
|
+
next if callback.to == [to]
|
|
194
|
+
|
|
195
|
+
callback = Statesman::Callback.new({
|
|
196
|
+
from: callback.from,
|
|
197
|
+
to: callback.to - [to],
|
|
198
|
+
callback: callback.callback,
|
|
199
|
+
})
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
callback
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
154
206
|
def validate_callback_type_and_class(callback_type, callback_class)
|
|
155
207
|
raise ArgumentError, "missing keyword: callback_type" if callback_type.nil?
|
|
156
208
|
raise ArgumentError, "missing keyword: callback_class" if callback_class.nil?
|
data/lib/statesman/version.rb
CHANGED
|
@@ -50,10 +50,11 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
|
|
|
50
50
|
|
|
51
51
|
shared_examples "testing methods" do
|
|
52
52
|
before do
|
|
53
|
-
|
|
53
|
+
case config_type
|
|
54
|
+
when :old
|
|
54
55
|
configure_old(MyActiveRecordModel, MyActiveRecordModelTransition)
|
|
55
56
|
configure_old(OtherActiveRecordModel, OtherActiveRecordModelTransition)
|
|
56
|
-
|
|
57
|
+
when :new
|
|
57
58
|
configure_new(MyActiveRecordModel, MyActiveRecordModelTransition)
|
|
58
59
|
configure_new(OtherActiveRecordModel, OtherActiveRecordModelTransition)
|
|
59
60
|
else
|
|
@@ -201,7 +202,6 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
|
|
|
201
202
|
MyActiveRecordModel.create
|
|
202
203
|
end
|
|
203
204
|
|
|
204
|
-
# rubocop:disable RSpec/ExampleLength
|
|
205
205
|
it do
|
|
206
206
|
expect do
|
|
207
207
|
ActiveRecord::Base.transaction do
|
|
@@ -210,7 +210,6 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
|
|
|
210
210
|
end
|
|
211
211
|
end.to_not change(MyStateMachine, :after_commit_callback_executed)
|
|
212
212
|
end
|
|
213
|
-
# rubocop:enable RSpec/ExampleLength
|
|
214
213
|
end
|
|
215
214
|
end
|
|
216
215
|
|
|
@@ -128,6 +128,7 @@ shared_examples_for "an adapter" do |adapter_class, transition_class, options =
|
|
|
128
128
|
|
|
129
129
|
it { is_expected.to be_a(transition_class) }
|
|
130
130
|
specify { expect(adapter.last.to_state.to_sym).to eq(:z) }
|
|
131
|
+
|
|
131
132
|
specify do
|
|
132
133
|
expect(adapter.last(force_reload: true).to_state.to_sym).to eq(:z)
|
|
133
134
|
end
|
|
@@ -7,6 +7,7 @@ describe Statesman do
|
|
|
7
7
|
subject(:error) { Statesman::InvalidStateError.new }
|
|
8
8
|
|
|
9
9
|
its(:message) { is_expected.to eq("Statesman::InvalidStateError") }
|
|
10
|
+
|
|
10
11
|
its "string matches its message" do
|
|
11
12
|
expect(error.to_s).to eq(error.message)
|
|
12
13
|
end
|
|
@@ -16,6 +17,7 @@ describe Statesman do
|
|
|
16
17
|
subject(:error) { Statesman::InvalidTransitionError.new }
|
|
17
18
|
|
|
18
19
|
its(:message) { is_expected.to eq("Statesman::InvalidTransitionError") }
|
|
20
|
+
|
|
19
21
|
its "string matches its message" do
|
|
20
22
|
expect(error.to_s).to eq(error.message)
|
|
21
23
|
end
|
|
@@ -25,6 +27,7 @@ describe Statesman do
|
|
|
25
27
|
subject(:error) { Statesman::InvalidTransitionError.new }
|
|
26
28
|
|
|
27
29
|
its(:message) { is_expected.to eq("Statesman::InvalidTransitionError") }
|
|
30
|
+
|
|
28
31
|
its "string matches its message" do
|
|
29
32
|
expect(error.to_s).to eq(error.message)
|
|
30
33
|
end
|
|
@@ -34,6 +37,7 @@ describe Statesman do
|
|
|
34
37
|
subject(:error) { Statesman::TransitionConflictError.new }
|
|
35
38
|
|
|
36
39
|
its(:message) { is_expected.to eq("Statesman::TransitionConflictError") }
|
|
40
|
+
|
|
37
41
|
its "string matches its message" do
|
|
38
42
|
expect(error.to_s).to eq(error.message)
|
|
39
43
|
end
|
|
@@ -43,6 +47,7 @@ describe Statesman do
|
|
|
43
47
|
subject(:error) { Statesman::MissingTransitionAssociation.new }
|
|
44
48
|
|
|
45
49
|
its(:message) { is_expected.to eq("Statesman::MissingTransitionAssociation") }
|
|
50
|
+
|
|
46
51
|
its "string matches its message" do
|
|
47
52
|
expect(error.to_s).to eq(error.message)
|
|
48
53
|
end
|
|
@@ -52,6 +57,7 @@ describe Statesman do
|
|
|
52
57
|
subject(:error) { Statesman::TransitionFailedError.new("from", "to") }
|
|
53
58
|
|
|
54
59
|
its(:message) { is_expected.to eq("Cannot transition from 'from' to 'to'") }
|
|
60
|
+
|
|
55
61
|
its "string matches its message" do
|
|
56
62
|
expect(error.to_s).to eq(error.message)
|
|
57
63
|
end
|
|
@@ -63,6 +69,7 @@ describe Statesman do
|
|
|
63
69
|
its(:message) do
|
|
64
70
|
is_expected.to eq("Guard on transition from: 'from' to 'to' returned false")
|
|
65
71
|
end
|
|
72
|
+
|
|
66
73
|
its "string matches its message" do
|
|
67
74
|
expect(error.to_s).to eq(error.message)
|
|
68
75
|
end
|
|
@@ -72,6 +79,7 @@ describe Statesman do
|
|
|
72
79
|
subject(:error) { Statesman::UnserializedMetadataError.new("foo") }
|
|
73
80
|
|
|
74
81
|
its(:message) { is_expected.to match(/foo#metadata is not serialized/) }
|
|
82
|
+
|
|
75
83
|
its "string matches its message" do
|
|
76
84
|
expect(error.to_s).to eq(error.message)
|
|
77
85
|
end
|
|
@@ -81,6 +89,7 @@ describe Statesman do
|
|
|
81
89
|
subject(:error) { Statesman::IncompatibleSerializationError.new("foo") }
|
|
82
90
|
|
|
83
91
|
its(:message) { is_expected.to match(/foo#metadata column type cannot be json/) }
|
|
92
|
+
|
|
84
93
|
its "string matches its message" do
|
|
85
94
|
expect(error.to_s).to eq(error.message)
|
|
86
95
|
end
|
|
@@ -27,6 +27,112 @@ describe Statesman::Machine do
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
describe ".remove_state" do
|
|
31
|
+
subject(:remove_state) { -> { machine.remove_state(:x) } }
|
|
32
|
+
|
|
33
|
+
before do
|
|
34
|
+
machine.class_eval do
|
|
35
|
+
state :x
|
|
36
|
+
state :y
|
|
37
|
+
state :z
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "removes the state" do
|
|
42
|
+
expect(remove_state).
|
|
43
|
+
to change(machine, :states).
|
|
44
|
+
from(match_array(%w[x y z])).
|
|
45
|
+
to(%w[y z])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "with a transition from the removed state" do
|
|
49
|
+
before { machine.transition from: :x, to: :y }
|
|
50
|
+
|
|
51
|
+
it "removes the transition" do
|
|
52
|
+
expect(remove_state).
|
|
53
|
+
to change(machine, :successors).
|
|
54
|
+
from({ "x" => ["y"] }).
|
|
55
|
+
to({})
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "with multiple transitions" do
|
|
59
|
+
before { machine.transition from: :x, to: :z }
|
|
60
|
+
|
|
61
|
+
it "removes all transitions" do
|
|
62
|
+
expect(remove_state).
|
|
63
|
+
to change(machine, :successors).
|
|
64
|
+
from({ "x" => %w[y z] }).
|
|
65
|
+
to({})
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "with a transition to the removed state" do
|
|
71
|
+
before { machine.transition from: :y, to: :x }
|
|
72
|
+
|
|
73
|
+
it "removes the transition" do
|
|
74
|
+
expect(remove_state).
|
|
75
|
+
to change(machine, :successors).
|
|
76
|
+
from({ "y" => ["x"] }).
|
|
77
|
+
to({})
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context "with multiple transitions" do
|
|
81
|
+
before { machine.transition from: :z, to: :x }
|
|
82
|
+
|
|
83
|
+
it "removes all transitions" do
|
|
84
|
+
expect(remove_state).
|
|
85
|
+
to change(machine, :successors).
|
|
86
|
+
from({ "y" => ["x"], "z" => ["x"] }).
|
|
87
|
+
to({})
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "with a callback from the removed state" do
|
|
93
|
+
before do
|
|
94
|
+
machine.class_eval do
|
|
95
|
+
transition from: :x, to: :y
|
|
96
|
+
transition from: :x, to: :z
|
|
97
|
+
guard_transition(from: :x) { return false }
|
|
98
|
+
guard_transition(from: :x, to: :z) { return true }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
let(:guards) do
|
|
103
|
+
[having_attributes(from: "x", to: []), having_attributes(from: "x", to: ["z"])]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "removes the guard" do
|
|
107
|
+
expect(remove_state).
|
|
108
|
+
to change(machine, :callbacks).
|
|
109
|
+
from(a_hash_including(guards: match_array(guards))).
|
|
110
|
+
to(a_hash_including(guards: []))
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context "with a callback to the removed state" do
|
|
115
|
+
before do
|
|
116
|
+
machine.class_eval do
|
|
117
|
+
transition from: :y, to: :x
|
|
118
|
+
guard_transition(to: :x) { return false }
|
|
119
|
+
guard_transition(from: :y, to: :x) { return true }
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
let(:guards) do
|
|
124
|
+
[having_attributes(from: nil, to: ["x"]), having_attributes(from: "y", to: ["x"])]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "removes the guard" do
|
|
128
|
+
expect(remove_state).
|
|
129
|
+
to change(machine, :callbacks).
|
|
130
|
+
from(a_hash_including(guards: match_array(guards))).
|
|
131
|
+
to(a_hash_including(guards: []))
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
30
136
|
describe ".retry_conflicts" do
|
|
31
137
|
subject(:transition_state) do
|
|
32
138
|
described_class.retry_conflicts(retry_attempts) do
|
|
@@ -170,6 +276,42 @@ describe Statesman::Machine do
|
|
|
170
276
|
end
|
|
171
277
|
end
|
|
172
278
|
|
|
279
|
+
describe ".remove_transitions" do
|
|
280
|
+
before do
|
|
281
|
+
machine.class_eval do
|
|
282
|
+
state :x
|
|
283
|
+
state :y
|
|
284
|
+
state :z
|
|
285
|
+
transition from: :x, to: :y
|
|
286
|
+
transition from: :x, to: :z
|
|
287
|
+
transition from: :y, to: :z
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
let(:initial_successors) { { "x" => %w[y z], "y" => ["z"] } }
|
|
292
|
+
|
|
293
|
+
it "removes the correct transitions when given a from state" do
|
|
294
|
+
expect { machine.remove_transitions(from: :x) }.
|
|
295
|
+
to change(machine, :successors).
|
|
296
|
+
from(initial_successors).
|
|
297
|
+
to({ "y" => ["z"] })
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it "removes the correct transitions when given a to state" do
|
|
301
|
+
expect { machine.remove_transitions(to: :z) }.
|
|
302
|
+
to change(machine, :successors).
|
|
303
|
+
from(initial_successors).
|
|
304
|
+
to({ "x" => ["y"] })
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
it "removes the correct transitions when given a from and to state" do
|
|
308
|
+
expect { machine.remove_transitions(from: :x, to: :z) }.
|
|
309
|
+
to change(machine, :successors).
|
|
310
|
+
from(initial_successors).
|
|
311
|
+
to({ "x" => ["y"], "y" => ["z"] })
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
173
315
|
describe ".validate_callback_condition" do
|
|
174
316
|
before do
|
|
175
317
|
machine.class_eval do
|
|
@@ -234,11 +376,9 @@ describe Statesman::Machine do
|
|
|
234
376
|
|
|
235
377
|
it "does not add a callback" do
|
|
236
378
|
expect do
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
nil
|
|
241
|
-
end
|
|
379
|
+
set_callback
|
|
380
|
+
rescue error_type
|
|
381
|
+
nil
|
|
242
382
|
end.to_not change(machine.callbacks[callback_store], :count)
|
|
243
383
|
end
|
|
244
384
|
end
|
|
@@ -64,7 +64,7 @@ class CreateMyActiveRecordModelMigration < MIGRATION_CLASS
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# TODO: make this a module we can extend from the app? Or a generator?
|
|
67
|
-
# rubocop:disable
|
|
67
|
+
# rubocop:disable Metrics/MethodLength
|
|
68
68
|
class CreateMyActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
|
69
69
|
def change
|
|
70
70
|
create_table :my_active_record_model_transitions do |t|
|
|
@@ -110,7 +110,7 @@ class CreateMyActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
|
-
# rubocop:enable
|
|
113
|
+
# rubocop:enable Metrics/MethodLength
|
|
114
114
|
|
|
115
115
|
class OtherActiveRecordModel < ActiveRecord::Base
|
|
116
116
|
has_many :other_active_record_model_transitions, autosave: false
|
|
@@ -144,7 +144,7 @@ class CreateOtherActiveRecordModelMigration < MIGRATION_CLASS
|
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
146
|
|
|
147
|
-
# rubocop:disable MethodLength
|
|
147
|
+
# rubocop:disable Metrics/MethodLength
|
|
148
148
|
class CreateOtherActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
|
149
149
|
def change
|
|
150
150
|
create_table :other_active_record_model_transitions do |t|
|
|
@@ -188,7 +188,7 @@ class CreateOtherActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
|
|
188
188
|
end
|
|
189
189
|
end
|
|
190
190
|
end
|
|
191
|
-
# rubocop:enable MethodLength
|
|
191
|
+
# rubocop:enable Metrics/MethodLength
|
|
192
192
|
|
|
193
193
|
class DropMostRecentColumn < MIGRATION_CLASS
|
|
194
194
|
def change
|
|
@@ -242,7 +242,7 @@ class CreateNamespacedARModelMigration < MIGRATION_CLASS
|
|
|
242
242
|
end
|
|
243
243
|
end
|
|
244
244
|
|
|
245
|
-
# rubocop:disable MethodLength
|
|
245
|
+
# rubocop:disable Metrics/MethodLength
|
|
246
246
|
class CreateNamespacedARModelTransitionMigration < MIGRATION_CLASS
|
|
247
247
|
def change
|
|
248
248
|
create_table :my_namespace_my_active_record_model_transitions do |t|
|
|
@@ -282,5 +282,5 @@ class CreateNamespacedARModelTransitionMigration < MIGRATION_CLASS
|
|
|
282
282
|
name: "index_namespace_model_transitions_parent_latest"
|
|
283
283
|
end
|
|
284
284
|
end
|
|
285
|
-
# rubocop:enable MethodLength
|
|
285
|
+
# rubocop:enable Metrics/MethodLength
|
|
286
286
|
end
|
data/statesman.gemspec
CHANGED
|
@@ -21,11 +21,11 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
22
22
|
spec.require_paths = ["lib"]
|
|
23
23
|
|
|
24
|
-
spec.required_ruby_version = ">= 2.
|
|
24
|
+
spec.required_ruby_version = ">= 2.7"
|
|
25
25
|
|
|
26
26
|
spec.add_development_dependency "ammeter", "~> 1.1"
|
|
27
|
-
spec.add_development_dependency "bundler", "~> 2
|
|
28
|
-
spec.add_development_dependency "gc_ruboconfig", "~> 2.
|
|
27
|
+
spec.add_development_dependency "bundler", "~> 2"
|
|
28
|
+
spec.add_development_dependency "gc_ruboconfig", "~> 2.26.0"
|
|
29
29
|
spec.add_development_dependency "mysql2", ">= 0.4", "< 0.6"
|
|
30
30
|
spec.add_development_dependency "pg", ">= 0.18", "<= 1.3"
|
|
31
31
|
spec.add_development_dependency "pry"
|
|
@@ -33,8 +33,8 @@ Gem::Specification.new do |spec|
|
|
|
33
33
|
spec.add_development_dependency "rake", "~> 13.0.0"
|
|
34
34
|
spec.add_development_dependency "rspec", "~> 3.1"
|
|
35
35
|
spec.add_development_dependency "rspec-its", "~> 1.1"
|
|
36
|
+
spec.add_development_dependency "rspec_junit_formatter", "~> 0.5.1"
|
|
36
37
|
spec.add_development_dependency "rspec-rails", "~> 3.1"
|
|
37
|
-
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.0"
|
|
38
38
|
spec.add_development_dependency "sqlite3", "~> 1.4.2"
|
|
39
39
|
spec.add_development_dependency "timecop", "~> 0.9.1"
|
|
40
40
|
|
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:
|
|
4
|
+
version: 10.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- GoCardless
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-05-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ammeter
|
|
@@ -30,28 +30,28 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 2
|
|
33
|
+
version: '2'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 2
|
|
40
|
+
version: '2'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: gc_ruboconfig
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 2.
|
|
47
|
+
version: 2.26.0
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 2.
|
|
54
|
+
version: 2.26.0
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: mysql2
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -163,33 +163,33 @@ dependencies:
|
|
|
163
163
|
- !ruby/object:Gem::Version
|
|
164
164
|
version: '1.1'
|
|
165
165
|
- !ruby/object:Gem::Dependency
|
|
166
|
-
name:
|
|
166
|
+
name: rspec_junit_formatter
|
|
167
167
|
requirement: !ruby/object:Gem::Requirement
|
|
168
168
|
requirements:
|
|
169
169
|
- - "~>"
|
|
170
170
|
- !ruby/object:Gem::Version
|
|
171
|
-
version:
|
|
171
|
+
version: 0.5.1
|
|
172
172
|
type: :development
|
|
173
173
|
prerelease: false
|
|
174
174
|
version_requirements: !ruby/object:Gem::Requirement
|
|
175
175
|
requirements:
|
|
176
176
|
- - "~>"
|
|
177
177
|
- !ruby/object:Gem::Version
|
|
178
|
-
version:
|
|
178
|
+
version: 0.5.1
|
|
179
179
|
- !ruby/object:Gem::Dependency
|
|
180
|
-
name:
|
|
180
|
+
name: rspec-rails
|
|
181
181
|
requirement: !ruby/object:Gem::Requirement
|
|
182
182
|
requirements:
|
|
183
183
|
- - "~>"
|
|
184
184
|
- !ruby/object:Gem::Version
|
|
185
|
-
version:
|
|
185
|
+
version: '3.1'
|
|
186
186
|
type: :development
|
|
187
187
|
prerelease: false
|
|
188
188
|
version_requirements: !ruby/object:Gem::Requirement
|
|
189
189
|
requirements:
|
|
190
190
|
- - "~>"
|
|
191
191
|
- !ruby/object:Gem::Version
|
|
192
|
-
version:
|
|
192
|
+
version: '3.1'
|
|
193
193
|
- !ruby/object:Gem::Dependency
|
|
194
194
|
name: sqlite3
|
|
195
195
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -226,9 +226,11 @@ extensions: []
|
|
|
226
226
|
extra_rdoc_files: []
|
|
227
227
|
files:
|
|
228
228
|
- ".circleci/config.yml"
|
|
229
|
+
- ".github/dependabot.yml"
|
|
229
230
|
- ".gitignore"
|
|
230
231
|
- ".rubocop.yml"
|
|
231
232
|
- ".rubocop_todo.yml"
|
|
233
|
+
- ".ruby-version"
|
|
232
234
|
- CHANGELOG.md
|
|
233
235
|
- CONTRIBUTING.md
|
|
234
236
|
- Gemfile
|
|
@@ -296,14 +298,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
296
298
|
requirements:
|
|
297
299
|
- - ">="
|
|
298
300
|
- !ruby/object:Gem::Version
|
|
299
|
-
version: '2.
|
|
301
|
+
version: '2.7'
|
|
300
302
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
301
303
|
requirements:
|
|
302
304
|
- - ">="
|
|
303
305
|
- !ruby/object:Gem::Version
|
|
304
306
|
version: '0'
|
|
305
307
|
requirements: []
|
|
306
|
-
rubygems_version: 3.
|
|
308
|
+
rubygems_version: 3.2.22
|
|
307
309
|
signing_key:
|
|
308
310
|
specification_version: 4
|
|
309
311
|
summary: A statesman-like state machine library
|