stator 0.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +8 -2
- data/.gitignore +1 -0
- data/Appraisals +4 -0
- data/Gemfile +1 -0
- data/gemfiles/activerecord_5.1.gemfile +1 -0
- data/gemfiles/activerecord_5.1.gemfile.lock +12 -2
- data/gemfiles/activerecord_5.2.gemfile +1 -0
- data/gemfiles/activerecord_5.2.gemfile.lock +12 -2
- data/gemfiles/activerecord_5.gemfile +12 -0
- data/gemfiles/activerecord_5.gemfile.lock +74 -0
- data/gemfiles/activerecord_6.0.gemfile +1 -0
- data/gemfiles/activerecord_6.0.gemfile.lock +12 -2
- data/gemfiles/activerecord_6.1.gemfile +1 -0
- data/gemfiles/activerecord_6.1.gemfile.lock +12 -2
- data/gemfiles/activerecord_7.0.gemfile +1 -0
- data/gemfiles/activerecord_7.0.gemfile.lock +12 -2
- data/lib/stator/alias.rb +51 -30
- data/lib/stator/integration.rb +42 -49
- data/lib/stator/machine.rb +59 -58
- data/lib/stator/model.rb +78 -73
- data/lib/stator/transition.rb +61 -60
- data/lib/stator/version.rb +3 -5
- data/lib/stator.rb +13 -0
- data/spec/model_spec.rb +203 -239
- data/spec/spec_helper.rb +6 -3
- data/spec/support/models.rb +26 -45
- data/spec/support/schema.rb +42 -42
- data/stator.gemspec +1 -1
- metadata +21 -5
data/spec/model_spec.rb
CHANGED
@@ -1,238 +1,201 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
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
|
-
|
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_in_database.should eql("pending")
|
15
|
-
end
|
16
|
-
|
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
|
22
6
|
|
23
|
-
|
24
|
-
u = User.new
|
25
|
-
u.state = "anythingelse"
|
7
|
+
let(:u) { User.new }
|
26
8
|
|
27
|
-
|
28
|
-
u.errors[:state].should eql(["is not a valid state"])
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should allow creation at any state" do
|
32
|
-
u = User.new(email: "doug@example.com")
|
33
|
-
u.state = "hyperactivated"
|
34
|
-
|
35
|
-
u.should be_valid
|
36
|
-
end
|
9
|
+
describe "basic operations" do
|
37
10
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
u.will_save_change_to_state?.should_not be true
|
42
|
-
u.state_in_database.should eq("pending")
|
43
|
-
u.state_before_last_save.should be nil
|
11
|
+
it 'should set the default state after initialization' do
|
12
|
+
u.state.to_sym.should eql(:pending)
|
13
|
+
end
|
44
14
|
|
45
|
-
|
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
|
46
19
|
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
50
24
|
|
51
|
-
|
25
|
+
it 'should ensure a valid state transition when given a bogus state' do
|
26
|
+
u.state = :anythingelse
|
52
27
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
28
|
+
u.should_not be_valid
|
29
|
+
u.errors[:state].should eql(['is not a valid state'])
|
30
|
+
end
|
57
31
|
|
58
|
-
|
59
|
-
|
32
|
+
it 'should allow creation at any state' do
|
33
|
+
u.email = 'doug@example.com'
|
34
|
+
u.state = :hyperactivated
|
60
35
|
|
61
|
-
|
36
|
+
u.should be_valid
|
37
|
+
end
|
62
38
|
|
63
|
-
|
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)
|
64
41
|
|
65
|
-
|
66
|
-
u.errors[:state].should_not be_empty
|
67
|
-
end
|
42
|
+
u.state = 'hyperactivated'
|
68
43
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
u.hyperactivate!
|
44
|
+
u.should_not be_valid
|
45
|
+
u.errors[:state].should_not be_empty
|
46
|
+
end
|
73
47
|
|
74
|
-
|
48
|
+
it 'should not allow a transition that is currently in a `to` state' do
|
49
|
+
u.email = 'fred@example.com'
|
50
|
+
u.activate!
|
75
51
|
u.hyperactivate!
|
76
|
-
}.should raise_error(/cannot transition to \"hyperactivated\" from \"hyperactivated\"/)
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should run conditional validations" do
|
80
|
-
u = User.new
|
81
|
-
u.state = "semiactivated"
|
82
|
-
u.should_not be_valid
|
83
52
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
it "should invoke callbacks" do
|
89
|
-
u = User.new(activated: true, email: "doug@example.com", name: "doug")
|
90
|
-
u.activated.should == true
|
91
|
-
|
92
|
-
u.deactivate
|
53
|
+
lambda {
|
54
|
+
u.hyperactivate!
|
55
|
+
}.should raise_error(/cannot transition to hyperactivated from hyperactivated/)
|
56
|
+
end
|
93
57
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
u.should be_persisted
|
98
|
-
end
|
58
|
+
it 'should run conditional validations' do
|
59
|
+
u.state = 'semiactivated'
|
60
|
+
u.should_not be_valid
|
99
61
|
|
100
|
-
|
101
|
-
|
102
|
-
|
62
|
+
u.errors[:state].should be_empty
|
63
|
+
u.errors[:email].should_not be_empty
|
64
|
+
end
|
103
65
|
|
104
|
-
|
66
|
+
it 'should invoke callbacks' do
|
67
|
+
u.assign_attributes(activated: true, email: 'doug@example.com', name: 'doug')
|
68
|
+
u.activated.should == true
|
105
69
|
|
106
|
-
|
107
|
-
u.activation_notification_published.should_not be true
|
70
|
+
u.deactivate
|
108
71
|
|
109
|
-
|
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
|
110
77
|
|
111
|
-
|
112
|
-
|
113
|
-
|
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
|
114
82
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
u.activate!
|
119
|
-
}.should raise_error(ActiveRecord::RecordInvalid)
|
120
|
-
end
|
83
|
+
it 'should allow for other fields to be used other than state' do
|
84
|
+
a = Animal.new
|
85
|
+
a.should be_valid
|
121
86
|
|
122
|
-
|
123
|
-
|
124
|
-
a.should be_valid
|
87
|
+
a.birth!
|
88
|
+
end
|
125
89
|
|
126
|
-
|
127
|
-
|
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
|
128
96
|
|
129
|
-
|
130
|
-
|
131
|
-
a.should_not be_grown_up
|
132
|
-
a.status = "grown_up"
|
133
|
-
a.save
|
134
|
-
end
|
97
|
+
it 'should allow multiple machines in the same model' do
|
98
|
+
f = Farm.new
|
135
99
|
|
136
|
-
|
137
|
-
|
138
|
-
f.should be_dirty
|
139
|
-
f.should be_house_dirty
|
100
|
+
f.should be_dirty
|
101
|
+
f.should be_house_dirty
|
140
102
|
|
141
|
-
|
103
|
+
f.cleanup
|
142
104
|
|
143
|
-
|
144
|
-
|
105
|
+
f.should_not be_dirty
|
106
|
+
f.should be_house_dirty
|
145
107
|
|
146
|
-
|
108
|
+
f.house_cleanup # the house namespace
|
147
109
|
|
148
|
-
|
149
|
-
|
110
|
+
f.should_not be_dirty
|
111
|
+
f.should_not be_house_dirty
|
112
|
+
end
|
150
113
|
|
151
|
-
|
152
|
-
|
153
|
-
|
114
|
+
it 'should allow saving to be skipped' do
|
115
|
+
f = Farm.new
|
116
|
+
f.cleanup(false)
|
154
117
|
|
155
|
-
|
156
|
-
|
118
|
+
f.should_not be_persisted
|
119
|
+
end
|
157
120
|
|
158
|
-
|
159
|
-
|
160
|
-
|
121
|
+
it 'should allow no initial state' do
|
122
|
+
f = Factory.new
|
123
|
+
f.state.should be_nil
|
161
124
|
|
162
|
-
|
125
|
+
f.construct.should eql(true)
|
163
126
|
|
164
|
-
|
165
|
-
|
127
|
+
f.state.should eql(:constructed)
|
128
|
+
end
|
166
129
|
|
167
|
-
|
168
|
-
|
169
|
-
u.email = "doug@example.com"
|
130
|
+
it 'should allow any transition if validations are opted out of' do
|
131
|
+
u.email = 'doug@example.com'
|
170
132
|
|
171
|
-
|
172
|
-
|
133
|
+
u.can_hyperactivate?.should eql(false)
|
134
|
+
u.hyperactivate.should eql(false)
|
173
135
|
|
174
|
-
|
136
|
+
u.current_state.should eql :pending
|
175
137
|
|
176
|
-
|
177
|
-
|
178
|
-
|
138
|
+
u.without_state_transition_validations do
|
139
|
+
u.can_hyperactivate?.should eql(true)
|
140
|
+
u.hyperactivate.should eql(true)
|
141
|
+
end
|
179
142
|
end
|
180
|
-
end
|
181
143
|
|
182
|
-
|
183
|
-
|
184
|
-
u.email = "doug@example.com"
|
144
|
+
it 'should skip tracking timestamps if opted out of' do
|
145
|
+
u.email = 'doug@example.com'
|
185
146
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
190
157
|
end
|
191
158
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
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)
|
197
163
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
164
|
+
threads << Thread.new do
|
165
|
+
sleep 0.5
|
166
|
+
nope.semiactivate!
|
167
|
+
end
|
202
168
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
skip.without_state_transition_tracking do
|
209
|
-
sleep 1
|
210
|
-
skip.semiactivate!
|
169
|
+
threads << Thread.new do
|
170
|
+
skip.without_state_transition_tracking do
|
171
|
+
sleep 1
|
172
|
+
skip.semiactivate!
|
173
|
+
end
|
211
174
|
end
|
212
|
-
end
|
213
175
|
|
214
|
-
|
176
|
+
threads.each(&:join)
|
215
177
|
|
216
|
-
|
217
|
-
|
218
|
-
|
178
|
+
nope.semiactivated_state_at.should_not be_nil
|
179
|
+
skip.semiactivated_state_at.should be_nil
|
180
|
+
end
|
219
181
|
|
220
|
-
|
221
|
-
|
222
|
-
|
182
|
+
it 'should not inherit _integration cache on dup' do
|
183
|
+
u.email = 'user@example.com'
|
184
|
+
u.save!
|
223
185
|
|
224
|
-
|
186
|
+
u_duped = u.dup
|
225
187
|
|
226
|
-
|
188
|
+
u.semiactivate!
|
227
189
|
|
228
|
-
|
190
|
+
u_duped_integration = u_duped.send(:_stator_integration)
|
229
191
|
|
230
|
-
|
231
|
-
|
192
|
+
u_duped_integration.state.should_not eql(u.state)
|
193
|
+
u_duped_integration.instance_values['record'].should eq(u_duped)
|
194
|
+
end
|
232
195
|
end
|
233
196
|
|
234
|
-
describe
|
235
|
-
it
|
197
|
+
describe 'helper methods' do
|
198
|
+
it 'should answer the question of whether the state is currently the one invoked' do
|
236
199
|
a = Animal.new
|
237
200
|
a.should be_unborn
|
238
201
|
a.should_not be_born
|
@@ -243,7 +206,7 @@ describe Stator::Model do
|
|
243
206
|
a.should_not be_unborn
|
244
207
|
end
|
245
208
|
|
246
|
-
it
|
209
|
+
it 'should determine if it can validly execute a transition' do
|
247
210
|
a = Animal.new
|
248
211
|
a.can_birth?.should eql(true)
|
249
212
|
|
@@ -253,18 +216,18 @@ describe Stator::Model do
|
|
253
216
|
end
|
254
217
|
end
|
255
218
|
|
256
|
-
describe
|
219
|
+
describe 'tracker methods' do
|
257
220
|
before do
|
258
|
-
Time.zone =
|
221
|
+
Time.zone = 'Eastern Time (US & Canada)'
|
259
222
|
end
|
260
223
|
|
261
|
-
it
|
224
|
+
it 'should store the initial state timestamp when the record is created' do
|
262
225
|
a = Animal.new
|
263
226
|
a.save
|
264
227
|
a.unborn_status_at.should be_within(1).of(Time.zone.now)
|
265
228
|
end
|
266
229
|
|
267
|
-
it
|
230
|
+
it 'should store when a record changed state for the first time' do
|
268
231
|
a = Animal.new
|
269
232
|
a.unborn_status_at.should be_nil
|
270
233
|
a.born_status_at.should be_nil
|
@@ -273,7 +236,7 @@ describe Stator::Model do
|
|
273
236
|
a.born_status_at.should be_within(1).of(Time.zone.now)
|
274
237
|
end
|
275
238
|
|
276
|
-
it
|
239
|
+
it 'should store when a record change states' do
|
277
240
|
a = Animal.new
|
278
241
|
a.status_changed_at.should be_nil
|
279
242
|
|
@@ -283,15 +246,14 @@ describe Stator::Model do
|
|
283
246
|
|
284
247
|
previous_status_changed_at = a.status_changed_at
|
285
248
|
|
286
|
-
a.name =
|
249
|
+
a.name = 'new name'
|
287
250
|
a.save
|
288
251
|
|
289
252
|
a.status_changed_at.should eql(previous_status_changed_at)
|
290
253
|
end
|
291
254
|
|
292
|
-
it
|
293
|
-
u =
|
294
|
-
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'
|
295
257
|
|
296
258
|
u.tagged_at.should be_nil
|
297
259
|
u.semiactivate!
|
@@ -300,35 +262,34 @@ describe Stator::Model do
|
|
300
262
|
u.tagged_at.should_not be_nil
|
301
263
|
end
|
302
264
|
|
303
|
-
it
|
304
|
-
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)
|
305
267
|
|
306
|
-
u =
|
307
|
-
u.
|
308
|
-
u.state = "semiactivated"
|
268
|
+
u.email = 'doug@example.com'
|
269
|
+
u.state = 'semiactivated'
|
309
270
|
u.semiactivated_state_at = t
|
310
271
|
u.save!
|
311
272
|
|
312
|
-
u.state.should eql(
|
273
|
+
u.state.should eql('semiactivated')
|
313
274
|
u.semiactivated_state_at.should eql(t)
|
314
275
|
end
|
315
276
|
|
316
|
-
it
|
317
|
-
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)
|
318
279
|
|
319
280
|
u = User.create!(
|
320
|
-
email:
|
321
|
-
state:
|
281
|
+
email: 'doug@example.com',
|
282
|
+
state: 'semiactivated',
|
322
283
|
semiactivated_state_at: t
|
323
284
|
)
|
324
285
|
|
325
|
-
u.state.should eql(
|
286
|
+
u.state.should eql('semiactivated')
|
326
287
|
u.semiactivated_state_at.should eql(t)
|
327
288
|
end
|
328
289
|
|
329
|
-
it
|
330
|
-
z = ZooKeeper.new(name:
|
331
|
-
z.employment_state.should eql(
|
290
|
+
it 'should allow opting into track by namespace' do
|
291
|
+
z = ZooKeeper.new(name: 'Doug')
|
292
|
+
z.employment_state.should eql('hired')
|
332
293
|
z.employment_fire!
|
333
294
|
z.fired_employment_state_at.should_not be_nil
|
334
295
|
|
@@ -341,52 +302,53 @@ describe Stator::Model do
|
|
341
302
|
z.ended_working_state_at.should be_nil
|
342
303
|
end
|
343
304
|
|
344
|
-
describe
|
345
|
-
it
|
346
|
-
t = Time.now
|
347
|
-
u = User.create!(
|
348
|
-
u.state_by?(:activated, Time.at(t.to_i + 1)).should be true
|
349
|
-
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
|
350
311
|
end
|
351
312
|
|
352
|
-
it
|
353
|
-
t = Time.now
|
354
|
-
u = User.create!(
|
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)
|
355
316
|
u.state_by?(:activated, t).should be true
|
356
317
|
u.activated_state_by?(t).should be true
|
357
318
|
end
|
358
319
|
|
359
|
-
it
|
360
|
-
t = Time.now
|
361
|
-
u = User.create!(
|
362
|
-
u.state_by?(:activated, Time.at(t.to_i - 1)).should be false
|
363
|
-
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
|
364
325
|
end
|
365
326
|
|
366
|
-
it
|
367
|
-
t = Time.now
|
368
|
-
u = User.create!(
|
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)
|
369
330
|
u.state_by?(:activated, t).should be false
|
370
331
|
u.activated_state_by?(t).should be false
|
371
332
|
end
|
372
333
|
|
373
|
-
it
|
374
|
-
u = User.create!(
|
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)
|
375
336
|
u.state_by?(:activated, nil).should be true
|
376
337
|
u.activated_state_by?(nil).should be true
|
377
338
|
end
|
378
339
|
|
379
|
-
it
|
380
|
-
u = User.create!(email:
|
340
|
+
it 'should be false when both are nil' do
|
341
|
+
u = User.create!(email: 'doug@example.com', activated_state_at: nil)
|
381
342
|
u.state_by?(:activated, nil).should be false
|
382
343
|
u.activated_state_by?(nil).should be false
|
383
344
|
end
|
384
345
|
end
|
385
346
|
end
|
386
347
|
|
387
|
-
describe
|
388
|
-
it
|
389
|
-
u = User.new(email:
|
348
|
+
describe 'aliasing' do
|
349
|
+
it 'should allow aliasing within the dsl' do
|
350
|
+
u = User.new(email: 'doug@example.com')
|
351
|
+
|
390
352
|
u.should respond_to(:active?)
|
391
353
|
u.should respond_to(:inactive?)
|
392
354
|
|
@@ -403,26 +365,28 @@ describe Stator::Model do
|
|
403
365
|
u.should be_active
|
404
366
|
u.should_not be_inactive
|
405
367
|
|
406
|
-
User::ACTIVE_STATES.should eql(%
|
407
|
-
User::INACTIVE_STATES.should eql(%
|
368
|
+
User::ACTIVE_STATES.should eql(%i[activated hyperactivated])
|
369
|
+
User::INACTIVE_STATES.should eql(%i[pending deactivated semiactivated])
|
408
370
|
|
409
|
-
User.active.to_sql.gsub(
|
410
|
-
|
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')")
|
411
375
|
end
|
412
376
|
|
413
|
-
it
|
377
|
+
it 'should evaluate inverses correctly' do
|
414
378
|
f = Farm.new
|
415
|
-
f.house_state =
|
379
|
+
f.house_state = 'dirty'
|
416
380
|
f.should_not be_house_cleaned
|
417
381
|
|
418
|
-
f.house_state =
|
382
|
+
f.house_state = 'disgusting'
|
419
383
|
f.should_not be_house_cleaned
|
420
384
|
|
421
|
-
f.house_state =
|
385
|
+
f.house_state = 'clean'
|
422
386
|
f.should be_house_cleaned
|
423
387
|
end
|
424
388
|
|
425
|
-
it
|
389
|
+
it 'should namespace aliases just like everything else' do
|
426
390
|
f = Farm.new
|
427
391
|
f.should respond_to(:house_cleaned?)
|
428
392
|
|
@@ -432,23 +396,23 @@ describe Stator::Model do
|
|
432
396
|
f.should be_house_cleaned
|
433
397
|
end
|
434
398
|
|
435
|
-
it
|
399
|
+
it 'should allow for explicit constant and scope names to be provided' do
|
436
400
|
User.should respond_to(:luke_warmers)
|
437
|
-
(
|
401
|
+
(!defined?(User::LUKE_WARMERS).nil?).should eql(true)
|
438
402
|
u = User.new
|
439
403
|
u.should respond_to(:luke_warm?)
|
440
404
|
end
|
441
405
|
|
442
|
-
it
|
406
|
+
it 'should not create constants or scopes by default' do
|
443
407
|
u = User.new
|
444
408
|
u.should respond_to(:iced_tea?)
|
445
|
-
(
|
409
|
+
(!defined?(User::ICED_TEA_STATES).nil?).should eql(false)
|
446
410
|
User.should_not respond_to(:iced_tea)
|
447
411
|
end
|
448
412
|
|
449
|
-
it
|
450
|
-
states = User._stator(
|
451
|
-
states.should eql(%
|
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])
|
452
416
|
end
|
453
417
|
end
|
454
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
|
-
:
|
25
|
-
:
|
27
|
+
adapter: :nulldb,
|
28
|
+
schema: 'support/schema.rb'
|
26
29
|
)
|
27
30
|
|
28
31
|
require 'support/models'
|