statesman 7.2.0 → 8.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +12 -12
- data/CHANGELOG.md +37 -0
- data/Gemfile +2 -2
- data/README.md +8 -2
- data/lib/generators/statesman/generator_helpers.rb +10 -2
- data/lib/statesman/adapters/active_record.rb +22 -14
- data/lib/statesman/adapters/active_record_queries.rb +5 -1
- data/lib/statesman/adapters/memory.rb +4 -0
- data/lib/statesman/machine.rb +4 -0
- data/lib/statesman/version.rb +1 -1
- data/spec/statesman/adapters/active_record_queries_spec.rb +25 -0
- data/spec/statesman/adapters/active_record_spec.rb +13 -0
- data/spec/support/active_record.rb +5 -0
- data/statesman.gemspec +11 -1
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa4a88371cc60e6698eb820b60096f681fbaedf8dbbbec5991d47db81daf695d
|
4
|
+
data.tar.gz: b67153a87f62722deb2053ddf661e79e7918fca5339f9a6829a086e30a2abf02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac43c11e5dc1791bac7a00ba8e84b459daad104be9c9b460626c7569e4b9bdf215f0d080b5151ff754ee109640e70d1ca6cec4b958acfeadd974aab6962f16fd
|
7
|
+
data.tar.gz: 965b0a4020631cb18c39ce6af8870f3e165c87058aaf25f40f217a71d51cf65345818f974569191156a5ed94021c63595cf049c45fa11b62e132b1631e6d3d46
|
data/.circleci/config.yml
CHANGED
@@ -86,11 +86,11 @@ jobs:
|
|
86
86
|
- POSTGRES_DB=statesman_test
|
87
87
|
- POSTGRES_PASSWORD=statesman
|
88
88
|
steps: *steps
|
89
|
-
build-ruby265-rails-
|
89
|
+
build-ruby265-rails-main-mysql:
|
90
90
|
docker:
|
91
91
|
- image: circleci/ruby:2.6.5-node
|
92
92
|
environment:
|
93
|
-
- RAILS_VERSION=
|
93
|
+
- RAILS_VERSION=main
|
94
94
|
- DATABASE_URL=mysql2://root@127.0.0.1/statesman_test
|
95
95
|
- DATABASE_DEPENDENCY_PORT=3306
|
96
96
|
- image: circleci/mysql:5.7.18
|
@@ -100,11 +100,11 @@ jobs:
|
|
100
100
|
- MYSQL_PASSWORD=
|
101
101
|
- MYSQL_DATABASE=statesman_test
|
102
102
|
steps: *steps
|
103
|
-
build-ruby265-rails-
|
103
|
+
build-ruby265-rails-main-postgres:
|
104
104
|
docker:
|
105
105
|
- image: circleci/ruby:2.6.5-node
|
106
106
|
environment:
|
107
|
-
- RAILS_VERSION=
|
107
|
+
- RAILS_VERSION=main
|
108
108
|
- DATABASE_URL=postgres://postgres@localhost/statesman_test
|
109
109
|
- EXCLUDE_MONGOID=true
|
110
110
|
- DATABASE_DEPENDENCY_PORT=5432
|
@@ -142,11 +142,11 @@ jobs:
|
|
142
142
|
- POSTGRES_DB=statesman_test
|
143
143
|
- POSTGRES_PASSWORD=statesman
|
144
144
|
steps: *steps
|
145
|
-
build-ruby270-rails-
|
145
|
+
build-ruby270-rails-main-mysql:
|
146
146
|
docker:
|
147
147
|
- image: circleci/ruby:2.7.0-node
|
148
148
|
environment:
|
149
|
-
- RAILS_VERSION=
|
149
|
+
- RAILS_VERSION=main
|
150
150
|
- DATABASE_URL=mysql2://root@127.0.0.1/statesman_test
|
151
151
|
- DATABASE_DEPENDENCY_PORT=3306
|
152
152
|
- image: circleci/mysql:5.7.18
|
@@ -156,11 +156,11 @@ jobs:
|
|
156
156
|
- MYSQL_PASSWORD=
|
157
157
|
- MYSQL_DATABASE=statesman_test
|
158
158
|
steps: *steps
|
159
|
-
build-ruby270-rails-
|
159
|
+
build-ruby270-rails-main-postgres:
|
160
160
|
docker:
|
161
161
|
- image: circleci/ruby:2.7.0-node
|
162
162
|
environment:
|
163
|
-
- RAILS_VERSION=
|
163
|
+
- RAILS_VERSION=main
|
164
164
|
- DATABASE_URL=postgres://postgres@localhost/statesman_test
|
165
165
|
- EXCLUDE_MONGOID=true
|
166
166
|
- DATABASE_DEPENDENCY_PORT=5432
|
@@ -179,9 +179,9 @@ workflows:
|
|
179
179
|
- build-ruby249-rails-524-postgres
|
180
180
|
- build-ruby265-rails-602-mysql
|
181
181
|
- build-ruby265-rails-602-postgres
|
182
|
-
- build-ruby265-rails-
|
183
|
-
- build-ruby265-rails-
|
182
|
+
- build-ruby265-rails-main-mysql
|
183
|
+
- build-ruby265-rails-main-postgres
|
184
184
|
- build-ruby270-rails-602-mysql
|
185
185
|
- build-ruby270-rails-602-postgres
|
186
|
-
- build-ruby270-rails-
|
187
|
-
- build-ruby270-rails-
|
186
|
+
- build-ruby270-rails-main-mysql
|
187
|
+
- build-ruby270-rails-main-postgres
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## v8.0.0 6th January 2021
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
- Use AR Arel table to type cast booleans in order to avoid deprecation warning [#421](https://github.com/gocardless/statesman/pull/421)
|
6
|
+
- Support relationships that doesn't use `id` as a Primary Key
|
7
|
+
[#422](https://github.com/gocardless/statesman/pull/422)
|
8
|
+
|
9
|
+
## v7.4.1 11th November 2020
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Add #reset method to state machine and adapter interfaces
|
14
|
+
[#417](https://github.com/gocardless/statesman/pull/417)
|
15
|
+
|
16
|
+
## v7.4.0 26th August 2020
|
17
|
+
|
18
|
+
### Added
|
19
|
+
|
20
|
+
- [Gem Metadata](https://guides.rubygems.org/specification-reference/#metadata)
|
21
|
+
to make finding changes between releases even easier.
|
22
|
+
|
23
|
+
## v7.3.0, 24th August 2020
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
|
27
|
+
- Use correct Arel for null [#409](https://github.com/gocardless/statesman/pull/#409)
|
28
|
+
|
29
|
+
## v7.2.0, 19th May 2020
|
30
|
+
|
31
|
+
### Changed
|
32
|
+
|
33
|
+
- Set non-empty password for postgres tests [#398](https://github.com/gocardless/statesman/pull/#398)
|
34
|
+
- Handle transitions differently for MySQL [#399](https://github.com/gocardless/statesman/pull/#399)
|
35
|
+
- pg requirement from >= 0.18, <= 1.1 to >= 0.18, <= 1.3 [#400](https://github.com/gocardless/statesman/pull/#400)
|
36
|
+
- Lazily enable mysql gaplock protection [#402](https://github.com/gocardless/statesman/pull/#402)
|
37
|
+
|
1
38
|
## v7.1.0, 10th Feb 2020
|
2
39
|
|
3
40
|
- Fix `to_s` on `TransitionFailedError` & `GuardFailedError`. `.message` and
|
data/Gemfile
CHANGED
@@ -5,8 +5,8 @@ source 'https://rubygems.org'
|
|
5
5
|
gemspec
|
6
6
|
|
7
7
|
# rubocop:disable Bundler/DuplicatedGem
|
8
|
-
if ENV['RAILS_VERSION'] == '
|
9
|
-
gem "rails", git: "https://github.com/rails/rails"
|
8
|
+
if ENV['RAILS_VERSION'] == 'main'
|
9
|
+
gem "rails", git: "https://github.com/rails/rails", branch: "main"
|
10
10
|
elsif ENV['RAILS_VERSION']
|
11
11
|
gem "rails", "~> #{ENV['RAILS_VERSION']}"
|
12
12
|
end
|
data/README.md
CHANGED
@@ -322,6 +322,10 @@ Machine.successors
|
|
322
322
|
#### `Machine#current_state`
|
323
323
|
Returns the current state based on existing transition objects.
|
324
324
|
|
325
|
+
Takes an optional keyword argument to force a reload of data from the
|
326
|
+
database.
|
327
|
+
e.g `current_state(force_reload: true)`
|
328
|
+
|
325
329
|
#### `Machine#in_state?(:state_1, :state_2, ...)`
|
326
330
|
Returns true if the machine is in any of the given states.
|
327
331
|
|
@@ -404,10 +408,12 @@ Model.in_state(:state_1).or(
|
|
404
408
|
#### Storing the state on the model object
|
405
409
|
|
406
410
|
If you wish to store the model state on the model directly, you can keep it up
|
407
|
-
to date using an `after_transition` hook
|
411
|
+
to date using an `after_transition` hook.
|
412
|
+
Combine it with the `after_commit` option to ensure the model state will only be
|
413
|
+
saved once the transition has made it irreversibly to the database:
|
408
414
|
|
409
415
|
```ruby
|
410
|
-
after_transition do |model, transition|
|
416
|
+
after_transition(after_commit: true) do |model, transition|
|
411
417
|
model.state = transition.to_state
|
412
418
|
model.save!
|
413
419
|
end
|
@@ -39,8 +39,16 @@ module Statesman
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def mysql?
|
42
|
-
|
43
|
-
|
42
|
+
configuration.try(:[], "adapter").try(:match, /mysql/)
|
43
|
+
end
|
44
|
+
|
45
|
+
# [] is deprecated and will be removed in 6.2
|
46
|
+
def configuration
|
47
|
+
if ActiveRecord::Base.configurations.respond_to?(:configs_for)
|
48
|
+
ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
|
49
|
+
else
|
50
|
+
ActiveRecord::Base.configurations[Rails.env]
|
51
|
+
end
|
44
52
|
end
|
45
53
|
|
46
54
|
def database_supports_partial_indexes?
|
@@ -67,6 +67,10 @@ module Statesman
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
def reset
|
71
|
+
@last_transition = nil
|
72
|
+
end
|
73
|
+
|
70
74
|
private
|
71
75
|
|
72
76
|
# rubocop:disable Metrics/MethodLength
|
@@ -113,7 +117,7 @@ module Statesman
|
|
113
117
|
to_state: to,
|
114
118
|
sort_key: next_sort_key,
|
115
119
|
metadata: metadata,
|
116
|
-
most_recent: not_most_recent_value,
|
120
|
+
most_recent: not_most_recent_value(db_cast: false),
|
117
121
|
}
|
118
122
|
end
|
119
123
|
|
@@ -301,19 +305,21 @@ module Statesman
|
|
301
305
|
end
|
302
306
|
|
303
307
|
def db_true
|
304
|
-
|
305
|
-
true,
|
306
|
-
transition_class.columns_hash["most_recent"],
|
307
|
-
)
|
308
|
-
::ActiveRecord::Base.connection.quote(value)
|
308
|
+
::ActiveRecord::Base.connection.quote(type_cast(true))
|
309
309
|
end
|
310
310
|
|
311
311
|
def db_false
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
::
|
312
|
+
::ActiveRecord::Base.connection.quote(type_cast(false))
|
313
|
+
end
|
314
|
+
|
315
|
+
def db_null
|
316
|
+
Arel::Nodes::SqlLiteral.new("NULL")
|
317
|
+
end
|
318
|
+
|
319
|
+
# Type casting against a column is deprecated and will be removed in Rails 6.2.
|
320
|
+
# See https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11
|
321
|
+
def type_cast(value)
|
322
|
+
::ActiveRecord::Base.connection.type_cast(value)
|
317
323
|
end
|
318
324
|
|
319
325
|
# Check whether the `most_recent` column allows null values. If it doesn't, set old
|
@@ -323,10 +329,12 @@ module Statesman
|
|
323
329
|
# indexes. By doing the conditioning on the column, rather than Rails' opinion of
|
324
330
|
# whether the database supports partial indexes, we're robust to DBs later adding
|
325
331
|
# support for partial indexes.
|
326
|
-
def not_most_recent_value
|
327
|
-
|
332
|
+
def not_most_recent_value(db_cast: true)
|
333
|
+
if transition_class.columns_hash["most_recent"].null == false
|
334
|
+
return db_cast ? db_false : false
|
335
|
+
end
|
328
336
|
|
329
|
-
nil
|
337
|
+
db_cast ? db_null : nil
|
330
338
|
end
|
331
339
|
end
|
332
340
|
|
@@ -104,7 +104,7 @@ module Statesman
|
|
104
104
|
|
105
105
|
def most_recent_transition_join
|
106
106
|
"LEFT OUTER JOIN #{model_table} AS #{most_recent_transition_alias} " \
|
107
|
-
"ON #{model.table_name}
|
107
|
+
"ON #{model.table_name}.#{model_primary_key} = " \
|
108
108
|
"#{most_recent_transition_alias}.#{model_foreign_key} " \
|
109
109
|
"AND #{most_recent_transition_alias}.most_recent = #{db_true}"
|
110
110
|
end
|
@@ -127,6 +127,10 @@ module Statesman
|
|
127
127
|
"and #{transition_class}."
|
128
128
|
end
|
129
129
|
|
130
|
+
def model_primary_key
|
131
|
+
transition_reflection.active_record_primary_key
|
132
|
+
end
|
133
|
+
|
130
134
|
def model_foreign_key
|
131
135
|
transition_reflection.foreign_key
|
132
136
|
end
|
data/lib/statesman/machine.rb
CHANGED
data/lib/statesman/version.rb
CHANGED
@@ -154,6 +154,31 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
+
context "with a custom primary key for the model" do
|
158
|
+
before do
|
159
|
+
# Switch to using OtherActiveRecordModelTransition, so the existing
|
160
|
+
# relation with MyActiveRecordModelTransition doesn't interfere with
|
161
|
+
# this spec.
|
162
|
+
# Configure the relationship to use a different primary key,
|
163
|
+
MyActiveRecordModel.send(:has_many,
|
164
|
+
:custom_name,
|
165
|
+
class_name: "OtherActiveRecordModelTransition",
|
166
|
+
primary_key: :external_id)
|
167
|
+
|
168
|
+
MyActiveRecordModel.class_eval do
|
169
|
+
def self.transition_class
|
170
|
+
OtherActiveRecordModelTransition
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe ".in_state" do
|
176
|
+
subject(:query) { MyActiveRecordModel.in_state(:succeeded) }
|
177
|
+
|
178
|
+
specify { expect { query }.to_not raise_error }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
157
182
|
context "after_commit transactional integrity" do
|
158
183
|
before do
|
159
184
|
MyStateMachine.class_eval do
|
@@ -355,6 +355,19 @@ describe Statesman::Adapters::ActiveRecord, active_record: true do
|
|
355
355
|
end
|
356
356
|
end
|
357
357
|
|
358
|
+
it "resets last with #reload" do
|
359
|
+
model.save!
|
360
|
+
ActiveRecord::Base.transaction do
|
361
|
+
model.state_machine.transition_to!(:succeeded)
|
362
|
+
# force to cache value in last_transition instance variable
|
363
|
+
expect(model.state_machine.current_state).to eq("succeeded")
|
364
|
+
raise ActiveRecord::Rollback
|
365
|
+
end
|
366
|
+
expect(model.state_machine.current_state).to eq("succeeded")
|
367
|
+
model.reload
|
368
|
+
expect(model.state_machine.current_state).to eq("initial")
|
369
|
+
end
|
370
|
+
|
358
371
|
context "with a namespaced model" do
|
359
372
|
before do
|
360
373
|
CreateNamespacedARModelMigration.migrate(:up)
|
data/statesman.gemspec
CHANGED
@@ -4,6 +4,8 @@ lib = File.expand_path("lib", __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require "statesman/version"
|
6
6
|
|
7
|
+
GITHUB_URL = "https://github.com/gocardless/statesman"
|
8
|
+
|
7
9
|
Gem::Specification.new do |spec|
|
8
10
|
spec.name = "statesman"
|
9
11
|
spec.version = Statesman::VERSION
|
@@ -11,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
11
13
|
spec.email = ["developers@gocardless.com"]
|
12
14
|
spec.description = "A statesman-like state machine library"
|
13
15
|
spec.summary = spec.description
|
14
|
-
spec.homepage =
|
16
|
+
spec.homepage = GITHUB_URL
|
15
17
|
spec.license = "MIT"
|
16
18
|
|
17
19
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
@@ -35,4 +37,12 @@ Gem::Specification.new do |spec|
|
|
35
37
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.0"
|
36
38
|
spec.add_development_dependency "sqlite3", "~> 1.4.2"
|
37
39
|
spec.add_development_dependency "timecop", "~> 0.9.1"
|
40
|
+
|
41
|
+
spec.metadata = {
|
42
|
+
"bug_tracker_uri" => "#{GITHUB_URL}/issues",
|
43
|
+
"changelog_uri" => "#{GITHUB_URL}/blob/master/CHANGELOG.md",
|
44
|
+
"documentation_uri" => "#{GITHUB_URL}/blob/master/README.md",
|
45
|
+
"homepage_uri" => GITHUB_URL,
|
46
|
+
"source_code_uri" => GITHUB_URL,
|
47
|
+
}
|
38
48
|
end
|
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: 8.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GoCardless
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ammeter
|
@@ -282,8 +282,13 @@ files:
|
|
282
282
|
homepage: https://github.com/gocardless/statesman
|
283
283
|
licenses:
|
284
284
|
- MIT
|
285
|
-
metadata:
|
286
|
-
|
285
|
+
metadata:
|
286
|
+
bug_tracker_uri: https://github.com/gocardless/statesman/issues
|
287
|
+
changelog_uri: https://github.com/gocardless/statesman/blob/master/CHANGELOG.md
|
288
|
+
documentation_uri: https://github.com/gocardless/statesman/blob/master/README.md
|
289
|
+
homepage_uri: https://github.com/gocardless/statesman
|
290
|
+
source_code_uri: https://github.com/gocardless/statesman
|
291
|
+
post_install_message:
|
287
292
|
rdoc_options: []
|
288
293
|
require_paths:
|
289
294
|
- lib
|
@@ -298,8 +303,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
298
303
|
- !ruby/object:Gem::Version
|
299
304
|
version: '0'
|
300
305
|
requirements: []
|
301
|
-
rubygems_version: 3.1.
|
302
|
-
signing_key:
|
306
|
+
rubygems_version: 3.1.2
|
307
|
+
signing_key:
|
303
308
|
specification_version: 4
|
304
309
|
summary: A statesman-like state machine library
|
305
310
|
test_files:
|