statesman 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ea9661229864328ca481ff132837554323967d265616d38c295c5fa94ca9103
4
- data.tar.gz: 8974f12e8e70d925f0b35e3753a9977d1ff94a1a76bf05c0a967535037ce6a24
3
+ metadata.gz: 171ee6b0234ee7909d9af5b91ee09e8cb397adac1c1e90db5e53b1e08413d137
4
+ data.tar.gz: fd445775c6f034e067b492e79191803c4b5f48127599e9395374fb7934ea9d8e
5
5
  SHA512:
6
- metadata.gz: ec7c81ee5c313377acaf35c1196ccf74036769bb945c636d93f56d346deda319534ea9dbeff87bbfe84a2f3d71d7a1a4ae3d435d80c2fa46dc43d2ff3304661a
7
- data.tar.gz: 78ed181ce45c7517f8617f61e26c20780f0f2c5b3a04236e4766761b985d42172774d05a54d05bcc2d72bc379eb2f6ed3fe68c122ce8989f19d3d5ba16d286af
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.3.0'
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
- updated_at = if ::ActiveRecord::Base.default_timezone == :utc
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, updated_at: updated_at)
100
+ most_recent.update_all(with_updated_timestamp(most_recent: false))
105
101
  else
106
- most_recent.update_all(most_recent: nil, updated_at: updated_at)
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
- def self.included(base)
7
- base.send(:serialize, :metadata, JSON)
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
@@ -1,3 +1,3 @@
1
1
  module Statesman
2
- VERSION = "3.3.0".freeze
2
+ VERSION = "3.4.0".freeze
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -11,6 +11,7 @@ require "action_controller"
11
11
  require "rspec/rails"
12
12
  require "support/active_record"
13
13
  require "rspec/its"
14
+ require "pry"
14
15
 
15
16
  RSpec.configure do |config|
16
17
  config.raise_errors_for_deprecations!
@@ -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", "~> 0.52.0"
33
- spec.add_development_dependency "sqlite3", "~> 1.3"
34
- spec.add_development_dependency "timecop", "~> 0.9.1"
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.3.0
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-01-05 00:00:00.000000000 Z
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.3
296
+ rubygems_version: 2.7.4
283
297
  signing_key:
284
298
  specification_version: 4
285
299
  summary: A statesman-like state machine library