stator 0.4.0 → 0.9.0.beta

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.
data/spec/model_spec.rb CHANGED
@@ -1,203 +1,201 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spec_helper"
3
+ require 'spec_helper'
4
4
 
5
5
  describe Stator::Model do
6
- it "should set the default state after initialization" do
7
- u = User.new
8
- u.state.should eql("pending")
9
- end
10
6
 
11
- it "should see the initial setting of the state as a change with the initial state as the previous value" do
12
- u = User.new
13
- u.state = "activated"
14
- u.state_was.should eql("pending")
15
- end
7
+ let(:u) { User.new }
16
8
 
17
- it "should not obstruct normal validations" do
18
- u = User.new
19
- u.should_not be_valid
20
- u.errors[:email].grep(/length/).should_not be_empty
21
- end
9
+ describe "basic operations" do
22
10
 
23
- it "should ensure a valid state transition when given a bogus state" do
24
- u = User.new
25
- u.state = "anythingelse"
11
+ it 'should set the default state after initialization' do
12
+ u.state.to_sym.should eql(:pending)
13
+ end
26
14
 
27
- u.should_not be_valid
28
- u.errors[:state].should eql(["is not a valid state"])
29
- end
15
+ it 'should see the initial setting of the state as a change with the initial state as the previous value' do
16
+ u.state = :activated
17
+ u.state_was.to_sym.should eql(:pending)
18
+ end
30
19
 
31
- it "should allow creation at any state" do
32
- u = User.new(email: "doug@example.com")
33
- u.state = "hyperactivated"
20
+ it 'should not obstruct normal validations' do
21
+ u.should_not be_valid
22
+ u.errors[:email].grep(/length/).should_not be_empty
23
+ end
34
24
 
35
- u.should be_valid
36
- end
25
+ it 'should ensure a valid state transition when given a bogus state' do
26
+ u.state = :anythingelse
37
27
 
38
- it "should ensure a valid state transition when given an illegal state based on the current state" do
39
- u = User.new
28
+ u.should_not be_valid
29
+ u.errors[:state].should eql(['is not a valid state'])
30
+ end
40
31
 
41
- allow(u).to receive(:new_record?).and_return(false)
32
+ it 'should allow creation at any state' do
33
+ u.email = 'doug@example.com'
34
+ u.state = :hyperactivated
42
35
 
43
- u.state = "hyperactivated"
36
+ u.should be_valid
37
+ end
44
38
 
45
- u.should_not be_valid
46
- u.errors[:state].should_not be_empty
47
- end
39
+ it 'should ensure a valid state transition when given an illegal state based on the current state' do
40
+ allow(u).to receive(:new_record?).and_return(false)
48
41
 
49
- it "should not allow a transition that is currently in a `to` state" do
50
- u = User.new(email: "fred@example.com")
51
- u.activate!
52
- u.hyperactivate!
42
+ u.state = 'hyperactivated'
53
43
 
54
- lambda {
44
+ u.should_not be_valid
45
+ u.errors[:state].should_not be_empty
46
+ end
47
+
48
+ it 'should not allow a transition that is currently in a `to` state' do
49
+ u.email = 'fred@example.com'
50
+ u.activate!
55
51
  u.hyperactivate!
56
- }.should raise_error(/cannot transition to \"hyperactivated\" from \"hyperactivated\"/)
57
- end
58
52
 
59
- it "should run conditional validations" do
60
- u = User.new
61
- u.state = "semiactivated"
62
- u.should_not be_valid
53
+ lambda {
54
+ u.hyperactivate!
55
+ }.should raise_error(/cannot transition to hyperactivated from hyperactivated/)
56
+ end
63
57
 
64
- u.errors[:state].should be_empty
65
- u.errors[:email].grep(/format/).should_not be_empty
66
- end
58
+ it 'should run conditional validations' do
59
+ u.state = 'semiactivated'
60
+ u.should_not be_valid
67
61
 
68
- it "should invoke callbacks" do
69
- u = User.new(activated: true, email: "doug@example.com", name: "doug")
70
- u.activated.should == true
62
+ u.errors[:state].should be_empty
63
+ u.errors[:email].should_not be_empty
64
+ end
71
65
 
72
- u.deactivate
66
+ it 'should invoke callbacks' do
67
+ u.assign_attributes(activated: true, email: 'doug@example.com', name: 'doug')
68
+ u.activated.should == true
73
69
 
74
- u.activated.should == false
75
- u.state.should eql("deactivated")
76
- u.activated_state_at.should be_nil
77
- u.should be_persisted
78
- end
70
+ u.deactivate
79
71
 
80
- it "should blow up if the record is invalid and a bang method is used" do
81
- u = User.new(email: "doug@other.com", name: "doug")
82
- lambda {
83
- u.activate!
84
- }.should raise_error(ActiveRecord::RecordInvalid)
85
- end
72
+ u.activated.should == false
73
+ u.state.should eql :deactivated
74
+ u.activated_state_at.should be_nil
75
+ u.should be_persisted
76
+ end
86
77
 
87
- it "should allow for other fields to be used other than state" do
88
- a = Animal.new
89
- a.should be_valid
78
+ it 'should blow up if the record is invalid and a bang method is used' do
79
+ u.assign_attributes(email: 'doug@other.com', name: 'doug')
80
+ -> { u.activate! }.should raise_error(ActiveRecord::RecordInvalid)
81
+ end
90
82
 
91
- a.birth!
92
- end
83
+ it 'should allow for other fields to be used other than state' do
84
+ a = Animal.new
85
+ a.should be_valid
93
86
 
94
- it "should create implicit transitions for state declarations" do
95
- a = Animal.new
96
- a.should_not be_grown_up
97
- a.status = "grown_up"
98
- a.save
99
- end
87
+ a.birth!
88
+ end
89
+
90
+ it 'should create implicit transitions for state declarations' do
91
+ a = Animal.new
92
+ a.should_not be_grown_up
93
+ a.status = 'grown_up'
94
+ a.save
95
+ end
100
96
 
101
- it "should allow multiple machines in the same model" do
102
- f = Farm.new
103
- f.should be_dirty
104
- f.should be_house_dirty
97
+ it 'should allow multiple machines in the same model' do
98
+ f = Farm.new
105
99
 
106
- f.cleanup
100
+ f.should be_dirty
101
+ f.should be_house_dirty
107
102
 
108
- f.should_not be_dirty
109
- f.should be_house_dirty
103
+ f.cleanup
110
104
 
111
- f.house_cleanup
105
+ f.should_not be_dirty
106
+ f.should be_house_dirty
112
107
 
113
- f.should_not be_house_dirty
114
- end
108
+ f.house_cleanup # the house namespace
115
109
 
116
- it "should allow saving to be skipped" do
117
- f = Farm.new
118
- f.cleanup(false)
110
+ f.should_not be_dirty
111
+ f.should_not be_house_dirty
112
+ end
119
113
 
120
- f.should_not be_persisted
121
- end
114
+ it 'should allow saving to be skipped' do
115
+ f = Farm.new
116
+ f.cleanup(false)
122
117
 
123
- it "should allow no initial state" do
124
- f = Factory.new
125
- f.state.should be_nil
118
+ f.should_not be_persisted
119
+ end
126
120
 
127
- f.construct.should eql(true)
121
+ it 'should allow no initial state' do
122
+ f = Factory.new
123
+ f.state.should be_nil
128
124
 
129
- f.state.should eql("constructed")
130
- end
125
+ f.construct.should eql(true)
126
+
127
+ f.state.should eql(:constructed)
128
+ end
131
129
 
132
- it "should allow any transition if validations are opted out of" do
133
- u = User.new
134
- u.email = "doug@example.com"
130
+ it 'should allow any transition if validations are opted out of' do
131
+ u.email = 'doug@example.com'
135
132
 
136
- u.can_hyperactivate?.should eql(false)
137
- u.hyperactivate.should eql(false)
133
+ u.can_hyperactivate?.should eql(false)
134
+ u.hyperactivate.should eql(false)
138
135
 
139
- u.state.should eql("pending")
136
+ u.current_state.should eql :pending
140
137
 
141
- u.without_state_transition_validations do
142
- u.can_hyperactivate?.should eql(true)
143
- u.hyperactivate.should eql(true)
138
+ u.without_state_transition_validations do
139
+ u.can_hyperactivate?.should eql(true)
140
+ u.hyperactivate.should eql(true)
141
+ end
144
142
  end
145
- end
146
143
 
147
- it "should skip tracking timestamps if opted out of" do
148
- u = User.new
149
- u.email = "doug@example.com"
144
+ it 'should skip tracking timestamps if opted out of' do
145
+ u.email = 'doug@example.com'
150
146
 
151
- u.without_state_transition_tracking do
152
- u.semiactivate!
153
- u.state.should eql("semiactivated")
154
- u.semiactivated_state_at.should be_nil
147
+ u.without_state_transition_tracking do
148
+ u.semiactivate!
149
+ u.state.should eql :semiactivated
150
+ u.semiactivated_state_at.should be_nil
151
+ end
152
+
153
+ # Make sure that tracking is ensured back to
154
+ # original value
155
+ u.activate!
156
+ u.activated_state_at.should_not be_nil
155
157
  end
156
158
 
157
- # Make sure that tracking is ensured back to
158
- # original value
159
- u.activate!
160
- u.activated_state_at.should_not be_nil
161
- end
159
+ it 'should skip tracking timestamps if opted out of with thread safety' do
160
+ threads = []
161
+ skip = User.new(email: 'skip@example.com', state: :pending)
162
+ nope = User.new(email: 'nope@example.com', state: :pending)
162
163
 
163
- it "should skip tracking timestamps if opted out of with thread safety" do
164
- threads = []
165
- skip = User.new(email: "skip@example.com")
166
- nope = User.new(email: "nope@example.com")
164
+ threads << Thread.new do
165
+ sleep 0.5
166
+ nope.semiactivate!
167
+ end
167
168
 
168
- threads << Thread.new do
169
- sleep 0.5
170
- nope.semiactivate!
171
- end
172
- threads << Thread.new do
173
- skip.without_state_transition_tracking do
174
- sleep 1
175
- skip.semiactivate!
169
+ threads << Thread.new do
170
+ skip.without_state_transition_tracking do
171
+ sleep 1
172
+ skip.semiactivate!
173
+ end
176
174
  end
177
- end
178
175
 
179
- threads.each(&:join)
176
+ threads.each(&:join)
180
177
 
181
- nope.semiactivated_state_at.should_not be_nil
182
- skip.semiactivated_state_at.should be_nil
183
- end
178
+ nope.semiactivated_state_at.should_not be_nil
179
+ skip.semiactivated_state_at.should be_nil
180
+ end
184
181
 
185
- it "should not inherit _integration cache on dup" do
186
- u = User.new(email: "user@example.com")
187
- u.save!
182
+ it 'should not inherit _integration cache on dup' do
183
+ u.email = 'user@example.com'
184
+ u.save!
188
185
 
189
- u_duped = u.dup
186
+ u_duped = u.dup
190
187
 
191
- u.semiactivate!
188
+ u.semiactivate!
192
189
 
193
- u_duped_integration = u_duped.send(:_integration)
190
+ u_duped_integration = u_duped.send(:_stator_integration)
194
191
 
195
- u_duped_integration.state.should_not eql(u.state)
196
- u_duped_integration.instance_values["record"].should eq(u_duped)
192
+ u_duped_integration.state.should_not eql(u.state)
193
+ u_duped_integration.instance_values['record'].should eq(u_duped)
194
+ end
197
195
  end
198
196
 
199
- describe "helper methods" do
200
- it "should answer the question of whether the state is currently the one invoked" do
197
+ describe 'helper methods' do
198
+ it 'should answer the question of whether the state is currently the one invoked' do
201
199
  a = Animal.new
202
200
  a.should be_unborn
203
201
  a.should_not be_born
@@ -208,7 +206,7 @@ describe Stator::Model do
208
206
  a.should_not be_unborn
209
207
  end
210
208
 
211
- it "should determine if it can validly execute a transition" do
209
+ it 'should determine if it can validly execute a transition' do
212
210
  a = Animal.new
213
211
  a.can_birth?.should eql(true)
214
212
 
@@ -218,18 +216,18 @@ describe Stator::Model do
218
216
  end
219
217
  end
220
218
 
221
- describe "tracker methods" do
219
+ describe 'tracker methods' do
222
220
  before do
223
- Time.zone = "Eastern Time (US & Canada)"
221
+ Time.zone = 'Eastern Time (US & Canada)'
224
222
  end
225
223
 
226
- it "should store the initial state timestamp when the record is created" do
224
+ it 'should store the initial state timestamp when the record is created' do
227
225
  a = Animal.new
228
226
  a.save
229
227
  a.unborn_status_at.should be_within(1).of(Time.zone.now)
230
228
  end
231
229
 
232
- it "should store when a record changed state for the first time" do
230
+ it 'should store when a record changed state for the first time' do
233
231
  a = Animal.new
234
232
  a.unborn_status_at.should be_nil
235
233
  a.born_status_at.should be_nil
@@ -238,7 +236,7 @@ describe Stator::Model do
238
236
  a.born_status_at.should be_within(1).of(Time.zone.now)
239
237
  end
240
238
 
241
- it "should store when a record change states" do
239
+ it 'should store when a record change states' do
242
240
  a = Animal.new
243
241
  a.status_changed_at.should be_nil
244
242
 
@@ -248,15 +246,14 @@ describe Stator::Model do
248
246
 
249
247
  previous_status_changed_at = a.status_changed_at
250
248
 
251
- a.name = "new name"
249
+ a.name = 'new name'
252
250
  a.save
253
251
 
254
252
  a.status_changed_at.should eql(previous_status_changed_at)
255
253
  end
256
254
 
257
- it "should prepend the setting of the timestamp so other callbacks can use it" do
258
- u = User.new
259
- u.email = "doug@example.com"
255
+ it 'should prepend the setting of the timestamp so other callbacks can use it' do
256
+ u.email = 'doug@example.com'
260
257
 
261
258
  u.tagged_at.should be_nil
262
259
  u.semiactivate!
@@ -265,35 +262,34 @@ describe Stator::Model do
265
262
  u.tagged_at.should_not be_nil
266
263
  end
267
264
 
268
- it "should respect the timestamp if explicitly provided" do
269
- t = Time.at(Time.now.to_i - 3600)
265
+ it 'should respect the timestamp if explicitly provided' do
266
+ t = Time.zone.at(Time.now.to_i - 3600)
270
267
 
271
- u = User.new
272
- u.email = "doug@example.com"
273
- u.state = "semiactivated"
268
+ u.email = 'doug@example.com'
269
+ u.state = 'semiactivated'
274
270
  u.semiactivated_state_at = t
275
271
  u.save!
276
272
 
277
- u.state.should eql("semiactivated")
273
+ u.state.should eql('semiactivated')
278
274
  u.semiactivated_state_at.should eql(t)
279
275
  end
280
276
 
281
- it "should respect the timestamp if explicitly provided via create" do
282
- t = Time.at(Time.now.to_i - 3600)
277
+ it 'should respect the timestamp if explicitly provided via create' do
278
+ t = Time.zone.at(Time.now.to_i - 3600)
283
279
 
284
280
  u = User.create!(
285
- email: "doug@example.com",
286
- state: "semiactivated",
281
+ email: 'doug@example.com',
282
+ state: 'semiactivated',
287
283
  semiactivated_state_at: t
288
284
  )
289
285
 
290
- u.state.should eql("semiactivated")
286
+ u.state.should eql('semiactivated')
291
287
  u.semiactivated_state_at.should eql(t)
292
288
  end
293
289
 
294
- it "should allow opting into track by namespace" do
295
- z = ZooKeeper.new(name: "Doug")
296
- z.employment_state.should eql("hired")
290
+ it 'should allow opting into track by namespace' do
291
+ z = ZooKeeper.new(name: 'Doug')
292
+ z.employment_state.should eql('hired')
297
293
  z.employment_fire!
298
294
  z.fired_employment_state_at.should_not be_nil
299
295
 
@@ -306,52 +302,53 @@ describe Stator::Model do
306
302
  z.ended_working_state_at.should be_nil
307
303
  end
308
304
 
309
- describe "#state_by?" do
310
- it "should be true when the transition is earlier" do
311
- t = Time.now
312
- u = User.create!( email: "doug@example.com", activated_state_at: t)
313
- u.state_by?(:activated, Time.at(t.to_i + 1)).should be true
314
- u.activated_state_by?(Time.at(t.to_i + 1)).should be true
305
+ describe '#state_by?' do
306
+ it 'should be true when the transition is earlier' do
307
+ t = Time.zone.now
308
+ u = User.create!(email: 'doug@example.com', activated_state_at: t)
309
+ u.state_by?(:activated, Time.zone.at(t.to_i + 1)).should be true
310
+ u.activated_state_by?(Time.zone.at(t.to_i + 1)).should be true
315
311
  end
316
312
 
317
- it "should be true when the transition is at the same time" do
318
- t = Time.now
319
- u = User.create!( email: "doug@example.com", activated_state_at: t)
313
+ it 'should be true when the transition is at the same time' do
314
+ t = Time.zone.now
315
+ u = User.create!(email: 'doug@example.com', activated_state_at: t)
320
316
  u.state_by?(:activated, t).should be true
321
317
  u.activated_state_by?(t).should be true
322
318
  end
323
319
 
324
- it "should be false when the transition is later" do
325
- t = Time.now
326
- u = User.create!( email: "doug@example.com", activated_state_at: t)
327
- u.state_by?(:activated, Time.at(t.to_i - 1)).should be false
328
- u.activated_state_by?(Time.at(t.to_i - 1)).should be false
320
+ it 'should be false when the transition is later' do
321
+ t = Time.zone.now
322
+ u = User.create!(email: 'doug@example.com', activated_state_at: t)
323
+ u.state_by?(:activated, Time.zone.at(t.to_i - 1)).should be false
324
+ u.activated_state_by?(Time.zone.at(t.to_i - 1)).should be false
329
325
  end
330
326
 
331
- it "should be false when the transition is nil" do
332
- t = Time.now
333
- u = User.create!( email: "doug@example.com", activated_state_at: nil)
327
+ it 'should be false when the transition is nil' do
328
+ t = Time.zone.now
329
+ u = User.create!(email: 'doug@example.com', activated_state_at: nil)
334
330
  u.state_by?(:activated, t).should be false
335
331
  u.activated_state_by?(t).should be false
336
332
  end
337
333
 
338
- it "should be true when the transition is not nil and the time is nil" do
339
- u = User.create!( email: "doug@example.com", activated_state_at: Time.now)
334
+ it 'should be true when the transition is not nil and the time is nil' do
335
+ u = User.create!(email: 'doug@example.com', activated_state_at: Time.zone.now)
340
336
  u.state_by?(:activated, nil).should be true
341
337
  u.activated_state_by?(nil).should be true
342
338
  end
343
339
 
344
- it "should be false when both are nil" do
345
- u = User.create!(email: "doug@example.com", activated_state_at: nil)
340
+ it 'should be false when both are nil' do
341
+ u = User.create!(email: 'doug@example.com', activated_state_at: nil)
346
342
  u.state_by?(:activated, nil).should be false
347
343
  u.activated_state_by?(nil).should be false
348
344
  end
349
345
  end
350
346
  end
351
347
 
352
- describe "aliasing" do
353
- it "should allow aliasing within the dsl" do
354
- u = User.new(email: "doug@example.com")
348
+ describe 'aliasing' do
349
+ it 'should allow aliasing within the dsl' do
350
+ u = User.new(email: 'doug@example.com')
351
+
355
352
  u.should respond_to(:active?)
356
353
  u.should respond_to(:inactive?)
357
354
 
@@ -368,26 +365,28 @@ describe Stator::Model do
368
365
  u.should be_active
369
366
  u.should_not be_inactive
370
367
 
371
- User::ACTIVE_STATES.should eql(%w[activated hyperactivated])
372
- User::INACTIVE_STATES.should eql(%w[pending deactivated semiactivated])
368
+ User::ACTIVE_STATES.should eql(%i[activated hyperactivated])
369
+ User::INACTIVE_STATES.should eql(%i[pending deactivated semiactivated])
373
370
 
374
- User.active.to_sql.gsub(" ", " ").should eq("SELECT users.* FROM users WHERE users.state IN ('activated', 'hyperactivated')")
375
- User.inactive.to_sql.gsub(" ", " ").should eq("SELECT users.* FROM users WHERE users.state IN ('pending', 'deactivated', 'semiactivated')")
371
+ User.active.to_sql.gsub(' ',
372
+ ' ').should eq("SELECT users.* FROM users WHERE users.state IN ('activated', 'hyperactivated')")
373
+ User.inactive.to_sql.gsub(' ',
374
+ ' ').should eq("SELECT users.* FROM users WHERE users.state IN ('pending', 'deactivated', 'semiactivated')")
376
375
  end
377
376
 
378
- it "should evaluate inverses correctly" do
377
+ it 'should evaluate inverses correctly' do
379
378
  f = Farm.new
380
- f.house_state = "dirty"
379
+ f.house_state = 'dirty'
381
380
  f.should_not be_house_cleaned
382
381
 
383
- f.house_state = "disgusting"
382
+ f.house_state = 'disgusting'
384
383
  f.should_not be_house_cleaned
385
384
 
386
- f.house_state = "clean"
385
+ f.house_state = 'clean'
387
386
  f.should be_house_cleaned
388
387
  end
389
388
 
390
- it "should namespace aliases just like everything else" do
389
+ it 'should namespace aliases just like everything else' do
391
390
  f = Farm.new
392
391
  f.should respond_to(:house_cleaned?)
393
392
 
@@ -397,23 +396,23 @@ describe Stator::Model do
397
396
  f.should be_house_cleaned
398
397
  end
399
398
 
400
- it "should allow for explicit constant and scope names to be provided" do
399
+ it 'should allow for explicit constant and scope names to be provided' do
401
400
  User.should respond_to(:luke_warmers)
402
- (!!defined?(User::LUKE_WARMERS)).should eql(true)
401
+ (!defined?(User::LUKE_WARMERS).nil?).should eql(true)
403
402
  u = User.new
404
403
  u.should respond_to(:luke_warm?)
405
404
  end
406
405
 
407
- it "should not create constants or scopes by default" do
406
+ it 'should not create constants or scopes by default' do
408
407
  u = User.new
409
408
  u.should respond_to(:iced_tea?)
410
- (!!defined?(User::ICED_TEA_STATES)).should eql(false)
409
+ (!defined?(User::ICED_TEA_STATES).nil?).should eql(false)
411
410
  User.should_not respond_to(:iced_tea)
412
411
  end
413
412
 
414
- it "should determine the full list of states correctly" do
415
- states = User._stator("").states
416
- states.should eql(%w[pending activated deactivated semiactivated hyperactivated])
413
+ it 'should determine the full list of states correctly' do
414
+ states = User._stator('').states
415
+ states.should eql(%i[pending activated deactivated semiactivated hyperactivated])
417
416
  end
418
417
  end
419
418
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by the `rspec --init` command. Conventionally, all
2
4
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
5
  # Require this file using `require "spec_helper"` to ensure that it is only
@@ -11,18 +13,19 @@ require 'active_support/core_ext'
11
13
  require 'stator'
12
14
 
13
15
  RSpec.configure do |config|
14
- config.treat_symbols_as_metadata_keys_with_true_values = true
15
16
  config.expect_with(:rspec) { |c| c.syntax = :should }
16
17
  config.run_all_when_everything_filtered = true
17
18
  config.filter_run :focus
18
19
 
20
+ config.raise_errors_for_deprecations!
21
+
19
22
  NullDB.configure do |c|
20
23
  c.project_root = File.dirname(__FILE__)
21
24
  end
22
25
 
23
26
  ActiveRecord::Base.establish_connection(
24
- :adapter => :nulldb,
25
- :schema => 'support/schema.rb'
27
+ adapter: :nulldb,
28
+ schema: 'support/schema.rb'
26
29
  )
27
30
 
28
31
  require 'support/models'