statesman 1.2.5 → 1.3.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
  SHA1:
3
- metadata.gz: 587d4c564a33a0b209ac791260a29d338f2ab19d
4
- data.tar.gz: 805d0d04ee16c728c602ff7cf3ac3b0ad45f0594
3
+ metadata.gz: 1bb8c427725b16ac0220c6084dedb633125bacbe
4
+ data.tar.gz: 69d38a1bb9c59c624c6f2182ec17516cefec51e7
5
5
  SHA512:
6
- metadata.gz: 6d6418d12ffcd11a87b34d5cf150ef79de2c98ad7d3eb9b5e0ff8985d8991a82ba23820344c99b52c6f6b3763b335a53935e797b88ba5d9733d20183539fc358
7
- data.tar.gz: 257f73f7c2f9051d943d1c135ff3f96761a14bc4de5c31e6a5f1c921ca96d14432b711ac3cb1213b843531384910b347986c77fcdc1fc5ed79de68b1f9420c8e
6
+ metadata.gz: 3a11a93626877eea776f71a075a868ab33add945898be2affe7c0cb47fb9a461a16bd3d5d9a831b0b9b45a121942bd455c5461dbf0e7187e3735090d4f130ea8
7
+ data.tar.gz: f748a6ca2dabfdc3390cbe4dac0def1a04874d93967ac40876a1680b2616f6136c341b7a1c0d10c9b2099271e97d60725c4e263e6a9f4eaefa41194134829592
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## v1.3.0 20 June 2015
2
+
3
+ - Rename `last_transition` alias in `ActiveRecordQueries` to `most_recent_#{model_name}`, to allow merging of two such queries (patch by [@isaacseymour](https://github.com/isaacseymour))
4
+
1
5
  ## v1.2.5 17 June 2015
2
6
 
3
7
  - Make `backfill_most_recent` rake task db-agnostic (patch by [@timothyp](https://github.com/timothyp))
data/README.md CHANGED
@@ -381,7 +381,7 @@ describe "guards" do
381
381
  end
382
382
 
383
383
  it "can transition from state foo to state baz" do
384
- expect { some_model.transition_to!(:baz).to_not raise_error
384
+ expect { some_model.transition_to!(:baz) }.to_not raise_error
385
385
  end
386
386
  end
387
387
  ```
@@ -30,26 +30,28 @@ module Statesman
30
30
 
31
31
  def in_state_with_most_recent(states)
32
32
  joins(most_recent_transition_join).
33
- where(states_where('last_transition', states), states)
33
+ where(states_where(most_recent_transition_alias, states), states)
34
34
  end
35
35
 
36
36
  def not_in_state_with_most_recent(states)
37
37
  joins(most_recent_transition_join).
38
- where("NOT (#{states_where('last_transition', states)})", states)
38
+ where("NOT (#{states_where(most_recent_transition_alias, states)})",
39
+ states)
39
40
  end
40
41
 
41
42
  def in_state_without_most_recent(states)
42
43
  joins(transition1_join).
43
44
  joins(transition2_join).
44
- where(states_where('transition1', states), states).
45
- where("transition2.id" => nil)
45
+ where(states_where(most_recent_transition_alias, states), states).
46
+ where("#{other_transition_alias}.id" => nil)
46
47
  end
47
48
 
48
49
  def not_in_state_without_most_recent(states)
49
50
  joins(transition1_join).
50
51
  joins(transition2_join).
51
- where("NOT (#{states_where('transition1', states)})", states).
52
- where("transition2.id" => nil)
52
+ where("NOT (#{states_where(most_recent_transition_alias, states)})",
53
+ states).
54
+ where("#{other_transition_alias}.id" => nil)
53
55
  end
54
56
 
55
57
  def transition_class
@@ -79,20 +81,24 @@ module Statesman
79
81
  end
80
82
 
81
83
  def transition1_join
82
- "LEFT OUTER JOIN #{model_table} transition1
83
- ON transition1.#{model_foreign_key} = #{table_name}.id"
84
+ "LEFT OUTER JOIN #{model_table} #{most_recent_transition_alias}
85
+ ON #{most_recent_transition_alias}.#{model_foreign_key} =
86
+ #{table_name}.id"
84
87
  end
85
88
 
86
89
  def transition2_join
87
- "LEFT OUTER JOIN #{model_table} transition2
88
- ON transition2.#{model_foreign_key} = #{table_name}.id
89
- AND transition2.sort_key > transition1.sort_key"
90
+ "LEFT OUTER JOIN #{model_table} #{other_transition_alias}
91
+ ON #{other_transition_alias}.#{model_foreign_key} =
92
+ #{table_name}.id
93
+ AND #{other_transition_alias}.sort_key >
94
+ #{most_recent_transition_alias}.sort_key"
90
95
  end
91
96
 
92
97
  def most_recent_transition_join
93
- "LEFT OUTER JOIN #{model_table} AS last_transition
94
- ON #{table_name}.id = last_transition.#{model_foreign_key}
95
- AND last_transition.most_recent = #{db_true}"
98
+ "LEFT OUTER JOIN #{model_table} AS #{most_recent_transition_alias}
99
+ ON #{table_name}.id =
100
+ #{most_recent_transition_alias}.#{model_foreign_key}
101
+ AND #{most_recent_transition_alias}.most_recent = #{db_true}"
96
102
  end
97
103
 
98
104
  def states_where(temporary_table_name, states)
@@ -105,6 +111,14 @@ module Statesman
105
111
  end
106
112
  end
107
113
 
114
+ def most_recent_transition_alias
115
+ "most_recent_#{transition_name.to_s.singularize}"
116
+ end
117
+
118
+ def other_transition_alias
119
+ "other_#{transition_name.to_s.singularize}"
120
+ end
121
+
108
122
  def db_true
109
123
  ::ActiveRecord::Base.connection.quote(true)
110
124
  end
@@ -1,3 +1,3 @@
1
1
  module Statesman
2
- VERSION = "1.2.5"
2
+ VERSION = "1.3.0"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -50,6 +50,8 @@ RSpec.configure do |config|
50
50
  my_active_record_model_transitions
51
51
  my_namespace_my_active_record_models
52
52
  my_namespace_my_active_record_model_transitions
53
+ other_active_record_models
54
+ other_active_record_model_transitions
53
55
  )
54
56
  tables.each do |table_name|
55
57
  sql = "DROP TABLE IF EXISTS #{table_name};"
@@ -75,5 +77,20 @@ RSpec.configure do |config|
75
77
  MyActiveRecordModelTransition.reset_column_information
76
78
  end
77
79
  end
80
+
81
+ def prepare_other_model_table
82
+ silence_stream(STDOUT) do
83
+ CreateOtherActiveRecordModelMigration.migrate(:up)
84
+ end
85
+ end
86
+
87
+ def prepare_other_transitions_table
88
+ silence_stream(STDOUT) do
89
+ CreateOtherActiveRecordModelTransitionMigration.migrate(:up)
90
+ OtherActiveRecordModelTransition.reset_column_information
91
+ end
92
+ end
93
+
94
+ MyNamespace::MyActiveRecordModelTransition.serialize(:metadata, JSON)
78
95
  end
79
96
  end
@@ -4,6 +4,8 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
4
4
  before do
5
5
  prepare_model_table
6
6
  prepare_transitions_table
7
+ prepare_other_model_table
8
+ prepare_other_transitions_table
7
9
  end
8
10
 
9
11
  before do
@@ -22,7 +24,21 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
22
24
  :initial
23
25
  end
24
26
  end
27
+
28
+ OtherActiveRecordModel.send(:include,
29
+ Statesman::Adapters::ActiveRecordQueries)
30
+ OtherActiveRecordModel.class_eval do
31
+ def self.transition_class
32
+ OtherActiveRecordModelTransition
33
+ end
34
+
35
+ def self.initial_state
36
+ :initial
37
+ end
38
+ end
25
39
  end
40
+ before { MyActiveRecordModel.send(:has_one, :other_active_record_model) }
41
+ before { OtherActiveRecordModel.send(:belongs_to, :my_active_record_model) }
26
42
 
27
43
  let!(:model) do
28
44
  model = MyActiveRecordModel.create
@@ -75,6 +91,16 @@ describe Statesman::Adapters::ActiveRecordQueries, active_record: true do
75
91
  it { is_expected.to include model }
76
92
  it { is_expected.to include other_model }
77
93
  end
94
+
95
+ context "merging two queries" do
96
+ subject do
97
+ MyActiveRecordModel.in_state(:succeeded).
98
+ joins(:other_active_record_model).
99
+ merge(OtherActiveRecordModel.in_state(:initial))
100
+ end
101
+
102
+ it { is_expected.to be_empty }
103
+ end
78
104
  end
79
105
 
80
106
  describe ".not_in_state" do
@@ -89,6 +89,83 @@ class CreateMyActiveRecordModelTransitionMigration < ActiveRecord::Migration
89
89
  end
90
90
  # rubocop:enable MethodLength
91
91
 
92
+ class OtherActiveRecordModel < ActiveRecord::Base
93
+ has_many :other_active_record_model_transitions
94
+ alias_method :transitions, :other_active_record_model_transitions
95
+
96
+ def state_machine
97
+ @state_machine ||= MyStateMachine.new(
98
+ self, transition_class: OtherActiveRecordModelTransition)
99
+ end
100
+
101
+ def metadata
102
+ super || {}
103
+ end
104
+ end
105
+
106
+ class OtherActiveRecordModelTransition < ActiveRecord::Base
107
+ include Statesman::Adapters::ActiveRecordTransition
108
+
109
+ belongs_to :other_active_record_model
110
+ serialize :metadata, JSON
111
+ end
112
+
113
+ class CreateOtherActiveRecordModelMigration < ActiveRecord::Migration
114
+ def change
115
+ create_table :other_active_record_models do |t|
116
+ t.string :current_state
117
+ t.integer :my_active_record_model_id
118
+ t.timestamps null: false
119
+ end
120
+ end
121
+ end
122
+
123
+ # rubocop:disable MethodLength
124
+ class CreateOtherActiveRecordModelTransitionMigration < ActiveRecord::Migration
125
+ def change
126
+ create_table :other_active_record_model_transitions do |t|
127
+ t.string :to_state
128
+ t.integer :other_active_record_model_id
129
+ t.integer :sort_key
130
+
131
+ # MySQL doesn't allow default values on text fields
132
+ if ActiveRecord::Base.connection.adapter_name == 'Mysql2'
133
+ t.text :metadata
134
+ else
135
+ t.text :metadata, default: '{}'
136
+ end
137
+
138
+ if Statesman::Adapters::ActiveRecord.database_supports_partial_indexes?
139
+ t.boolean :most_recent, default: true, null: false
140
+ else
141
+ t.boolean :most_recent, default: true
142
+ end
143
+
144
+ t.timestamps null: false
145
+ end
146
+
147
+ add_index :other_active_record_model_transitions,
148
+ [:other_active_record_model_id, :sort_key],
149
+ unique: true, name: "other_sort_key_index"
150
+
151
+ if Statesman::Adapters::ActiveRecord.database_supports_partial_indexes?
152
+ add_index :other_active_record_model_transitions,
153
+ [:other_active_record_model_id, :most_recent],
154
+ unique: true,
155
+ where: "most_recent",
156
+ name: "index_other_active_record_model_transitions_"\
157
+ "parent_most_recent"
158
+ else
159
+ add_index :other_active_record_model_transitions,
160
+ [:other_active_record_model_id, :most_recent],
161
+ unique: true,
162
+ name: "index_other_active_record_model_transitions_"\
163
+ "parent_most_recent"
164
+ end
165
+ end
166
+ end
167
+
168
+ # rubocop:enable MethodLength
92
169
  class DropMostRecentColumn < ActiveRecord::Migration
93
170
  def change
94
171
  remove_index :my_active_record_model_transitions,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statesman
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Marr
@@ -9,202 +9,202 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-06-17 00:00:00.000000000 Z
12
+ date: 2015-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '1.3'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.3'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - '>='
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - '>='
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ~>
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '3.1'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ~>
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '3.1'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rspec-rails
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ~>
60
+ - - "~>"
61
61
  - !ruby/object:Gem::Version
62
62
  version: '3.1'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ~>
67
+ - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '3.1'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: rspec-its
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ~>
74
+ - - "~>"
75
75
  - !ruby/object:Gem::Version
76
76
  version: '1.1'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ~>
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '1.1'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: guard-rspec
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ~>
88
+ - - "~>"
89
89
  - !ruby/object:Gem::Version
90
90
  version: '4.3'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ~>
95
+ - - "~>"
96
96
  - !ruby/object:Gem::Version
97
97
  version: '4.3'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: rubocop
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - ~>
102
+ - - "~>"
103
103
  - !ruby/object:Gem::Version
104
104
  version: 0.30.0
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - ~>
109
+ - - "~>"
110
110
  - !ruby/object:Gem::Version
111
111
  version: 0.30.0
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: guard-rubocop
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
- - - ~>
116
+ - - "~>"
117
117
  - !ruby/object:Gem::Version
118
118
  version: '1.2'
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - ~>
123
+ - - "~>"
124
124
  - !ruby/object:Gem::Version
125
125
  version: '1.2'
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: sqlite3
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  requirements:
130
- - - ~>
130
+ - - "~>"
131
131
  - !ruby/object:Gem::Version
132
132
  version: '1.3'
133
133
  type: :development
134
134
  prerelease: false
135
135
  version_requirements: !ruby/object:Gem::Requirement
136
136
  requirements:
137
- - - ~>
137
+ - - "~>"
138
138
  - !ruby/object:Gem::Version
139
139
  version: '1.3'
140
140
  - !ruby/object:Gem::Dependency
141
141
  name: mongoid
142
142
  requirement: !ruby/object:Gem::Requirement
143
143
  requirements:
144
- - - '>='
144
+ - - ">="
145
145
  - !ruby/object:Gem::Version
146
146
  version: '3.1'
147
147
  type: :development
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
- - - '>='
151
+ - - ">="
152
152
  - !ruby/object:Gem::Version
153
153
  version: '3.1'
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: rails
156
156
  requirement: !ruby/object:Gem::Requirement
157
157
  requirements:
158
- - - '>='
158
+ - - ">="
159
159
  - !ruby/object:Gem::Version
160
160
  version: '3.2'
161
161
  type: :development
162
162
  prerelease: false
163
163
  version_requirements: !ruby/object:Gem::Requirement
164
164
  requirements:
165
- - - '>='
165
+ - - ">="
166
166
  - !ruby/object:Gem::Version
167
167
  version: '3.2'
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: pg
170
170
  requirement: !ruby/object:Gem::Requirement
171
171
  requirements:
172
- - - ~>
172
+ - - "~>"
173
173
  - !ruby/object:Gem::Version
174
174
  version: '0.18'
175
175
  type: :development
176
176
  prerelease: false
177
177
  version_requirements: !ruby/object:Gem::Requirement
178
178
  requirements:
179
- - - ~>
179
+ - - "~>"
180
180
  - !ruby/object:Gem::Version
181
181
  version: '0.18'
182
182
  - !ruby/object:Gem::Dependency
183
183
  name: mysql2
184
184
  requirement: !ruby/object:Gem::Requirement
185
185
  requirements:
186
- - - ~>
186
+ - - "~>"
187
187
  - !ruby/object:Gem::Version
188
188
  version: '0.3'
189
189
  type: :development
190
190
  prerelease: false
191
191
  version_requirements: !ruby/object:Gem::Requirement
192
192
  requirements:
193
- - - ~>
193
+ - - "~>"
194
194
  - !ruby/object:Gem::Version
195
195
  version: '0.3'
196
196
  - !ruby/object:Gem::Dependency
197
197
  name: ammeter
198
198
  requirement: !ruby/object:Gem::Requirement
199
199
  requirements:
200
- - - ~>
200
+ - - "~>"
201
201
  - !ruby/object:Gem::Version
202
202
  version: '1.1'
203
203
  type: :development
204
204
  prerelease: false
205
205
  version_requirements: !ruby/object:Gem::Requirement
206
206
  requirements:
207
- - - ~>
207
+ - - "~>"
208
208
  - !ruby/object:Gem::Version
209
209
  version: '1.1'
210
210
  description: A statesmanlike state machine library
@@ -214,9 +214,9 @@ executables: []
214
214
  extensions: []
215
215
  extra_rdoc_files: []
216
216
  files:
217
- - .gitignore
218
- - .rubocop.yml
219
- - .travis.yml
217
+ - ".gitignore"
218
+ - ".rubocop.yml"
219
+ - ".travis.yml"
220
220
  - CHANGELOG.md
221
221
  - CONTRIBUTING.md
222
222
  - Gemfile
@@ -288,17 +288,17 @@ require_paths:
288
288
  - lib
289
289
  required_ruby_version: !ruby/object:Gem::Requirement
290
290
  requirements:
291
- - - '>='
291
+ - - ">="
292
292
  - !ruby/object:Gem::Version
293
293
  version: '0'
294
294
  required_rubygems_version: !ruby/object:Gem::Requirement
295
295
  requirements:
296
- - - '>='
296
+ - - ">="
297
297
  - !ruby/object:Gem::Version
298
298
  version: '0'
299
299
  requirements: []
300
300
  rubyforge_project:
301
- rubygems_version: 2.2.2
301
+ rubygems_version: 2.4.1
302
302
  signing_key:
303
303
  specification_version: 4
304
304
  summary: A statesmanlike state machine library
@@ -326,3 +326,4 @@ test_files:
326
326
  - spec/support/active_record.rb
327
327
  - spec/support/generators_shared_examples.rb
328
328
  - spec/support/mongoid.rb
329
+ has_rdoc: