statesman 3.3.0 → 3.4.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/CHANGELOG.md +4 -0
- data/README.md +6 -1
- data/lib/generators/statesman/templates/active_record_transition_model.rb.erb +7 -0
- data/lib/generators/statesman/templates/create_migration.rb.erb +4 -0
- data/lib/statesman/adapters/active_record.rb +15 -7
- data/lib/statesman/adapters/active_record_transition.rb +9 -2
- data/lib/statesman/version.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/statesman/adapters/active_record_spec.rb +40 -0
- data/spec/support/active_record.rb +8 -2
- data/statesman.gemspec +4 -3
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 171ee6b0234ee7909d9af5b91ee09e8cb397adac1c1e90db5e53b1e08413d137
|
4
|
+
data.tar.gz: fd445775c6f034e067b492e79191803c4b5f48127599e9395374fb7934ea9d8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b88f58d64734af53bbf5155059a5f56ad96578c7d7be57e0f4b52b77bf1f57db6629438d91da1acd5068ea456d16893070555a720e1d153f7b5111cfa2f4ce2
|
7
|
+
data.tar.gz: 3e07fafb2c37ae74a9c60f38ac186110d7f01e2024ff0361948b8dc039e282845748f31737f25a36d228eb8188788f2f7be8db2e1e2d978486e82153c82a7474
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## v3.4.0, 12 February 2018
|
2
|
+
|
3
|
+
- When unsetting the `most_recent` flag during a transition, don't assume that transitions have an `updated_at` attribute, but rather allow the "updated timestamp column" to be re-configured or disabled entirely (patch by [@timrogers](https://github.com/timrogers))
|
4
|
+
|
1
5
|
## v3.3.0, 5 January 2018
|
2
6
|
|
3
7
|
- Touch `updated_at` on transitions when unsetting `most_recent` flag (patch by [@NGMarmaduke](https://github.com/NGMarmaduke))
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ protection.
|
|
29
29
|
To get started, just add Statesman to your `Gemfile`, and then run `bundle`:
|
30
30
|
|
31
31
|
```ruby
|
32
|
-
gem 'statesman', '~> 3.
|
32
|
+
gem 'statesman', '~> 3.4.0'
|
33
33
|
```
|
34
34
|
|
35
35
|
## Usage
|
@@ -137,6 +137,11 @@ Generate the transition model:
|
|
137
137
|
$ rails g statesman:active_record_transition Order OrderTransition
|
138
138
|
```
|
139
139
|
|
140
|
+
If you're using the ActiveRecord adapter and decide not to include the default
|
141
|
+
`updated_at` column in your transition table, you'll need to configure the
|
142
|
+
`updated_timestamp_column` option on the transition class, setting it to another column
|
143
|
+
name (e.g. `:updated_on`) or `nil`.
|
144
|
+
|
140
145
|
And add an association from the parent model:
|
141
146
|
|
142
147
|
`app/models/order.rb`:
|
@@ -1,6 +1,13 @@
|
|
1
1
|
class <%= klass %> < <%= Statesman::Utils.rails_5_or_higher? ? 'ApplicationRecord' : 'ActiveRecord::Base' %>
|
2
2
|
include Statesman::Adapters::ActiveRecordTransition
|
3
3
|
|
4
|
+
# If your transition table doesn't have the default `updated_at` timestamp column,
|
5
|
+
# you'll need to configure the `updated_timestamp_column` option, setting it to
|
6
|
+
# another column name (e.g. `:updated_on`) or `nil`.
|
7
|
+
#
|
8
|
+
# self.updated_timestamp_column = :updated_on
|
9
|
+
# self.updated_timestamp_column = nil
|
10
|
+
|
4
11
|
<%- unless Statesman::Utils.rails_4_or_higher? -%>
|
5
12
|
attr_accessible :to_state, :metadata, :sort_key
|
6
13
|
|
@@ -6,6 +6,10 @@ class Create<%= migration_class_name %> < ActiveRecord::Migration<%= "[#{ActiveR
|
|
6
6
|
t.integer :sort_key, null: false
|
7
7
|
t.integer :<%= parent_id %>, null: false
|
8
8
|
t.boolean :most_recent<%= ", null: false" if database_supports_partial_indexes? %>
|
9
|
+
|
10
|
+
# If you decide not to include an updated timestamp column in your transition
|
11
|
+
# table, you'll need to configure the `updated_timestamp_column` setting in your
|
12
|
+
# migration class.
|
9
13
|
t.timestamps null: false
|
10
14
|
end
|
11
15
|
|
@@ -88,11 +88,7 @@ module Statesman
|
|
88
88
|
|
89
89
|
def unset_old_most_recent
|
90
90
|
most_recent = transitions_for_parent.where(most_recent: true)
|
91
|
-
|
92
|
-
Time.now.utc
|
93
|
-
else
|
94
|
-
Time.now
|
95
|
-
end
|
91
|
+
|
96
92
|
# Check whether the `most_recent` column allows null values. If it
|
97
93
|
# doesn't, set old records to `false`, otherwise, set them to `NULL`.
|
98
94
|
#
|
@@ -101,9 +97,9 @@ module Statesman
|
|
101
97
|
# rather than Rails' opinion of whether the database supports partial
|
102
98
|
# indexes, we're robust to DBs later adding support for partial indexes.
|
103
99
|
if transition_class.columns_hash["most_recent"].null == false
|
104
|
-
most_recent.update_all(most_recent: false
|
100
|
+
most_recent.update_all(with_updated_timestamp(most_recent: false))
|
105
101
|
else
|
106
|
-
most_recent.update_all(most_recent: nil
|
102
|
+
most_recent.update_all(with_updated_timestamp(most_recent: nil))
|
107
103
|
end
|
108
104
|
end
|
109
105
|
|
@@ -125,6 +121,18 @@ module Statesman
|
|
125
121
|
e.message.include?(@transition_class.table_name) &&
|
126
122
|
(e.message.include?("sort_key") || e.message.include?("most_recent"))
|
127
123
|
end
|
124
|
+
|
125
|
+
def with_updated_timestamp(params)
|
126
|
+
return params if @transition_class.updated_timestamp_column.nil?
|
127
|
+
|
128
|
+
timestamp = if ::ActiveRecord::Base.default_timezone == :utc
|
129
|
+
Time.now.utc
|
130
|
+
else
|
131
|
+
Time.now
|
132
|
+
end
|
133
|
+
|
134
|
+
params.merge(@transition_class.updated_timestamp_column => timestamp)
|
135
|
+
end
|
128
136
|
end
|
129
137
|
end
|
130
138
|
end
|
@@ -3,8 +3,15 @@ require "json"
|
|
3
3
|
module Statesman
|
4
4
|
module Adapters
|
5
5
|
module ActiveRecordTransition
|
6
|
-
|
7
|
-
|
6
|
+
DEFAULT_UPDATED_TIMESTAMP_COLUMN = :updated_at
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
serialize :metadata, JSON
|
12
|
+
|
13
|
+
class_attribute :updated_timestamp_column
|
14
|
+
self.updated_timestamp_column = DEFAULT_UPDATED_TIMESTAMP_COLUMN
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|
data/lib/statesman/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -163,6 +163,46 @@ describe Statesman::Adapters::ActiveRecord, active_record: true do
|
|
163
163
|
to(change { previous_transition.reload.updated_at })
|
164
164
|
end
|
165
165
|
|
166
|
+
context "with a custom updated timestamp column set" do
|
167
|
+
around do |example|
|
168
|
+
MyActiveRecordModelTransition.updated_timestamp_column.tap do |original_value|
|
169
|
+
MyActiveRecordModelTransition.updated_timestamp_column = :updated_on
|
170
|
+
example.run
|
171
|
+
MyActiveRecordModelTransition.updated_timestamp_column = original_value
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
it "touches the previous transition's updated_on timestamp" do
|
176
|
+
expect { Timecop.freeze(Time.now + 1.day) { create } }.
|
177
|
+
to(change { previous_transition.reload.updated_on })
|
178
|
+
end
|
179
|
+
|
180
|
+
it "doesn't update the updated_at column" do
|
181
|
+
expect { Timecop.freeze(Time.now + 5.seconds) { create } }.
|
182
|
+
to_not(change { previous_transition.reload.updated_at })
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context "with no updated timestamp column set" do
|
187
|
+
around do |example|
|
188
|
+
MyActiveRecordModelTransition.updated_timestamp_column.tap do |original_value|
|
189
|
+
MyActiveRecordModelTransition.updated_timestamp_column = nil
|
190
|
+
example.run
|
191
|
+
MyActiveRecordModelTransition.updated_timestamp_column = original_value
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
it "just updates the most_recent" do
|
196
|
+
expect { Timecop.freeze(Time.now + 5.seconds) { create } }.
|
197
|
+
to(change { previous_transition.reload.most_recent })
|
198
|
+
end
|
199
|
+
|
200
|
+
it "doesn't update the updated_at column" do
|
201
|
+
expect { Timecop.freeze(Time.now + 5.seconds) { create } }.
|
202
|
+
to_not(change { previous_transition.reload.updated_at })
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
166
206
|
context "and a query on the parent model's state is made" do
|
167
207
|
context "in a before action" do
|
168
208
|
it "still has the old state" do
|
@@ -50,7 +50,7 @@ class CreateMyActiveRecordModelMigration < MIGRATION_CLASS
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# TODO: make this a module we can extend from the app? Or a generator?
|
53
|
-
# rubocop:disable MethodLength
|
53
|
+
# rubocop:disable MethodLength, Metrics/AbcSize
|
54
54
|
class CreateMyActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
55
55
|
def change
|
56
56
|
create_table :my_active_record_model_transitions do |t|
|
@@ -72,6 +72,10 @@ class CreateMyActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
|
72
72
|
end
|
73
73
|
|
74
74
|
t.timestamps null: false
|
75
|
+
|
76
|
+
# We'll use this to test customising the updated_timestamp_column setting on the
|
77
|
+
# transition class.
|
78
|
+
t.date :updated_on
|
75
79
|
end
|
76
80
|
|
77
81
|
add_index :my_active_record_model_transitions,
|
@@ -94,7 +98,7 @@ class CreateMyActiveRecordModelTransitionMigration < MIGRATION_CLASS
|
|
94
98
|
end
|
95
99
|
end
|
96
100
|
end
|
97
|
-
# rubocop:enable MethodLength
|
101
|
+
# rubocop:enable MethodLength, Metrics/AbcSize
|
98
102
|
|
99
103
|
class OtherActiveRecordModel < ActiveRecord::Base
|
100
104
|
has_many :other_active_record_model_transitions, autosave: false
|
@@ -206,6 +210,8 @@ module MyNamespace
|
|
206
210
|
end
|
207
211
|
|
208
212
|
class MyActiveRecordModelTransition < ActiveRecord::Base
|
213
|
+
include Statesman::Adapters::ActiveRecordTransition
|
214
|
+
|
209
215
|
belongs_to :my_active_record_model,
|
210
216
|
class_name: "MyNamespace::MyActiveRecordModel"
|
211
217
|
serialize :metadata, JSON
|
data/statesman.gemspec
CHANGED
@@ -23,13 +23,14 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
24
|
spec.add_development_dependency "mysql2", "~> 0.4"
|
25
25
|
spec.add_development_dependency "pg", "~> 0.18"
|
26
|
+
spec.add_development_dependency "pry"
|
26
27
|
spec.add_development_dependency "rails", ">= 3.2"
|
27
28
|
spec.add_development_dependency "rake", "~> 12.3.0"
|
28
29
|
spec.add_development_dependency "rspec", "~> 3.1"
|
29
30
|
spec.add_development_dependency "rspec-its", "~> 1.1"
|
30
31
|
spec.add_development_dependency "rspec-rails", "~> 3.1"
|
31
32
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.3.0"
|
32
|
-
spec.add_development_dependency "rubocop",
|
33
|
-
spec.add_development_dependency "sqlite3",
|
34
|
-
spec.add_development_dependency "timecop",
|
33
|
+
spec.add_development_dependency "rubocop", "~> 0.52.0"
|
34
|
+
spec.add_development_dependency "sqlite3", "~> 1.3"
|
35
|
+
spec.add_development_dependency "timecop", "~> 0.9.1"
|
35
36
|
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: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GoCardless
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ammeter
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.18'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rails
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -279,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
279
293
|
version: '0'
|
280
294
|
requirements: []
|
281
295
|
rubyforge_project:
|
282
|
-
rubygems_version: 2.7.
|
296
|
+
rubygems_version: 2.7.4
|
283
297
|
signing_key:
|
284
298
|
specification_version: 4
|
285
299
|
summary: A statesman-like state machine library
|