active_record_doctor 1.10.0 → 1.12.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/README.md +15 -15
- data/lib/active_record_doctor/detectors/base.rb +194 -53
- data/lib/active_record_doctor/detectors/extraneous_indexes.rb +36 -34
- data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +2 -5
- data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +87 -37
- data/lib/active_record_doctor/detectors/incorrect_length_validation.rb +7 -10
- data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +16 -9
- data/lib/active_record_doctor/detectors/missing_foreign_keys.rb +2 -4
- data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +13 -11
- data/lib/active_record_doctor/detectors/missing_presence_validation.rb +14 -7
- data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +70 -35
- data/lib/active_record_doctor/detectors/short_primary_key_type.rb +4 -4
- data/lib/active_record_doctor/detectors/undefined_table_references.rb +2 -2
- data/lib/active_record_doctor/detectors/unindexed_deleted_at.rb +5 -13
- data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +35 -11
- data/lib/active_record_doctor/logger/dummy.rb +11 -0
- data/lib/active_record_doctor/logger/hierarchical.rb +22 -0
- data/lib/active_record_doctor/logger.rb +6 -0
- data/lib/active_record_doctor/rake/task.rb +10 -1
- data/lib/active_record_doctor/runner.rb +8 -3
- data/lib/active_record_doctor/utils.rb +21 -0
- data/lib/active_record_doctor/version.rb +1 -1
- data/lib/active_record_doctor.rb +5 -0
- data/lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb +14 -14
- data/test/active_record_doctor/detectors/disable_test.rb +1 -1
- data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +59 -6
- data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +7 -7
- data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +175 -57
- data/test/active_record_doctor/detectors/incorrect_length_validation_test.rb +16 -14
- data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +35 -1
- data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +46 -23
- data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +55 -27
- data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +216 -47
- data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +5 -0
- data/test/active_record_doctor/detectors/undefined_table_references_test.rb +11 -13
- data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +39 -1
- data/test/active_record_doctor/runner_test.rb +18 -19
- data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +16 -6
- data/test/setup.rb +10 -6
- metadata +23 -7
- data/test/model_factory.rb +0 -128
@@ -3,30 +3,30 @@
|
|
3
3
|
class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Test
|
4
4
|
def test_invoking_no_callbacks_suggests_delete_all
|
5
5
|
create_table(:companies) do
|
6
|
-
end.
|
6
|
+
end.define_model do
|
7
7
|
has_many :users, dependent: :destroy
|
8
8
|
end
|
9
9
|
|
10
10
|
create_table(:users) do |t|
|
11
11
|
t.references :companies
|
12
|
-
end.
|
12
|
+
end.define_model do
|
13
13
|
belongs_to :company
|
14
14
|
end
|
15
15
|
|
16
16
|
assert_problems(<<~OUTPUT)
|
17
|
-
use `dependent: :delete_all` or similar on
|
17
|
+
use `dependent: :delete_all` or similar on TransientRecord::Models::Company.users - associated model TransientRecord::Models::User has no callbacks and can be deleted in bulk
|
18
18
|
OUTPUT
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_invoking_callbacks_does_not_suggest_delete_all
|
22
22
|
create_table(:companies) do
|
23
|
-
end.
|
23
|
+
end.define_model do
|
24
24
|
has_many :users, dependent: :destroy
|
25
25
|
end
|
26
26
|
|
27
27
|
create_table(:users) do |t|
|
28
28
|
t.references :companies
|
29
|
-
end.
|
29
|
+
end.define_model do
|
30
30
|
belongs_to :company
|
31
31
|
|
32
32
|
before_destroy :log
|
@@ -40,13 +40,13 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
40
40
|
|
41
41
|
def test_skipping_callbacks_suggests_destroy
|
42
42
|
create_table(:companies) do
|
43
|
-
end.
|
43
|
+
end.define_model do
|
44
44
|
has_many :users, dependent: :delete_all
|
45
45
|
end
|
46
46
|
|
47
47
|
create_table(:users) do |t|
|
48
48
|
t.references :companies
|
49
|
-
end.
|
49
|
+
end.define_model do
|
50
50
|
belongs_to :company
|
51
51
|
|
52
52
|
before_destroy :log
|
@@ -56,19 +56,19 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
56
56
|
end
|
57
57
|
|
58
58
|
assert_problems(<<~OUTPUT)
|
59
|
-
use `dependent: :destroy` or similar on
|
59
|
+
use `dependent: :destroy` or similar on TransientRecord::Models::Company.users - associated model TransientRecord::Models::User has callbacks that are currently skipped
|
60
60
|
OUTPUT
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_invoking_callbacks_does_not_suggest_destroy
|
64
64
|
create_table(:companies) do
|
65
|
-
end.
|
65
|
+
end.define_model do
|
66
66
|
has_many :users, dependent: :destroy
|
67
67
|
end
|
68
68
|
|
69
69
|
create_table(:users) do |t|
|
70
70
|
t.references :companies
|
71
|
-
end.
|
71
|
+
end.define_model do
|
72
72
|
belongs_to :company
|
73
73
|
|
74
74
|
before_destroy :log
|
@@ -82,102 +82,102 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
82
82
|
|
83
83
|
def test_works_on_has_one
|
84
84
|
create_table(:companies) do
|
85
|
-
end.
|
86
|
-
has_one :owner, class_name: "
|
85
|
+
end.define_model do
|
86
|
+
has_one :owner, class_name: "TransientRecord::Models::User", dependent: :destroy
|
87
87
|
end
|
88
88
|
|
89
89
|
create_table(:users) do |t|
|
90
90
|
t.references :companies
|
91
|
-
end.
|
91
|
+
end.define_model do
|
92
92
|
belongs_to :company
|
93
93
|
end
|
94
94
|
|
95
95
|
assert_problems(<<~OUTPUT)
|
96
|
-
use `dependent: :delete` or similar on
|
96
|
+
use `dependent: :delete` or similar on TransientRecord::Models::Company.owner - associated model TransientRecord::Models::User has no callbacks and can be deleted without loading
|
97
97
|
OUTPUT
|
98
98
|
end
|
99
99
|
|
100
100
|
def test_works_on_belongs_to
|
101
101
|
create_table(:companies) do
|
102
|
-
end.
|
102
|
+
end.define_model do
|
103
103
|
has_many :users
|
104
104
|
end
|
105
105
|
|
106
106
|
create_table(:users) do |t|
|
107
107
|
t.references :company
|
108
|
-
end.
|
108
|
+
end.define_model do
|
109
109
|
belongs_to :company, dependent: :destroy
|
110
110
|
end
|
111
111
|
|
112
112
|
assert_problems(<<~OUTPUT)
|
113
|
-
use `dependent: :delete` or similar on
|
113
|
+
use `dependent: :delete` or similar on TransientRecord::Models::User.company - associated model TransientRecord::Models::Company has no callbacks and can be deleted without loading
|
114
114
|
OUTPUT
|
115
115
|
end
|
116
116
|
|
117
117
|
def test_no_foreign_key_on_second_level_association
|
118
118
|
create_table(:companies) do
|
119
|
-
end.
|
119
|
+
end.define_model do
|
120
120
|
has_many :users
|
121
121
|
has_many :projects
|
122
122
|
end
|
123
123
|
|
124
124
|
create_table(:users) do |t|
|
125
125
|
t.references :company
|
126
|
-
end.
|
126
|
+
end.define_model do
|
127
127
|
belongs_to :company, dependent: :destroy
|
128
128
|
end
|
129
129
|
|
130
130
|
create_table(:projects) do |t|
|
131
131
|
t.references :company
|
132
|
-
end.
|
132
|
+
end.define_model do
|
133
133
|
belongs_to :company
|
134
134
|
end
|
135
135
|
|
136
136
|
assert_problems(<<~OUTPUT)
|
137
|
-
use `dependent: :delete` or similar on
|
137
|
+
use `dependent: :delete` or similar on TransientRecord::Models::User.company - associated model TransientRecord::Models::Company has no callbacks and can be deleted without loading
|
138
138
|
OUTPUT
|
139
139
|
end
|
140
140
|
|
141
141
|
def test_nullify_foreign_key_on_second_level_association
|
142
142
|
create_table(:companies) do
|
143
|
-
end.
|
143
|
+
end.define_model do
|
144
144
|
has_many :users
|
145
145
|
has_many :projects
|
146
146
|
end
|
147
147
|
|
148
148
|
create_table(:users) do |t|
|
149
149
|
t.references :company
|
150
|
-
end.
|
150
|
+
end.define_model do
|
151
151
|
belongs_to :company, dependent: :destroy
|
152
152
|
end
|
153
153
|
|
154
154
|
create_table(:projects) do |t|
|
155
155
|
t.references :company, foreign_key: { on_delete: :nullify }
|
156
|
-
end.
|
156
|
+
end.define_model do
|
157
157
|
belongs_to :company
|
158
158
|
end
|
159
159
|
|
160
160
|
assert_problems(<<~OUTPUT)
|
161
|
-
use `dependent: :delete` or similar on
|
161
|
+
use `dependent: :delete` or similar on TransientRecord::Models::User.company - associated model TransientRecord::Models::Company has no callbacks and can be deleted without loading
|
162
162
|
OUTPUT
|
163
163
|
end
|
164
164
|
|
165
165
|
def test_cascade_foreign_key_and_callbacks_on_second_level_association
|
166
166
|
create_table(:companies) do
|
167
|
-
end.
|
167
|
+
end.define_model do
|
168
168
|
has_many :users
|
169
169
|
has_many :projects
|
170
170
|
end
|
171
171
|
|
172
172
|
create_table(:users) do |t|
|
173
173
|
t.references :company
|
174
|
-
end.
|
174
|
+
end.define_model do
|
175
175
|
belongs_to :company, dependent: :delete
|
176
176
|
end
|
177
177
|
|
178
178
|
create_table(:projects) do |t|
|
179
179
|
t.references :company, foreign_key: { on_delete: :cascade }
|
180
|
-
end.
|
180
|
+
end.define_model do
|
181
181
|
belongs_to :company
|
182
182
|
|
183
183
|
before_destroy :log
|
@@ -187,26 +187,26 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
187
187
|
end
|
188
188
|
|
189
189
|
assert_problems(<<~OUTPUT)
|
190
|
-
use `dependent: :destroy` or similar on
|
190
|
+
use `dependent: :destroy` or similar on TransientRecord::Models::User.company - associated model TransientRecord::Models::Company has callbacks that are currently skipped
|
191
191
|
OUTPUT
|
192
192
|
end
|
193
193
|
|
194
194
|
def test_cascade_foreign_key_and_no_callbacks_on_second_level_association
|
195
195
|
create_table(:companies) do
|
196
|
-
end.
|
196
|
+
end.define_model do
|
197
197
|
has_many :users
|
198
198
|
has_many :projects
|
199
199
|
end
|
200
200
|
|
201
201
|
create_table(:users) do |t|
|
202
202
|
t.references :company
|
203
|
-
end.
|
203
|
+
end.define_model do
|
204
204
|
belongs_to :company, dependent: :delete
|
205
205
|
end
|
206
206
|
|
207
207
|
create_table(:projects) do |t|
|
208
208
|
t.references :company, foreign_key: { on_delete: :cascade }
|
209
|
-
end.
|
209
|
+
end.define_model do
|
210
210
|
belongs_to :company
|
211
211
|
end
|
212
212
|
|
@@ -215,13 +215,13 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
215
215
|
|
216
216
|
def test_no_dependent_suggests_nothing
|
217
217
|
create_table(:companies) do
|
218
|
-
end.
|
218
|
+
end.define_model do
|
219
219
|
has_many :users
|
220
220
|
end
|
221
221
|
|
222
222
|
create_table(:users) do |t|
|
223
223
|
t.references :companies
|
224
|
-
end.
|
224
|
+
end.define_model do
|
225
225
|
belongs_to :company
|
226
226
|
end
|
227
227
|
|
@@ -232,22 +232,22 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
232
232
|
create_table(:images) do |t|
|
233
233
|
t.bigint :imageable_id, null: false
|
234
234
|
t.string :imageable_type, null: true
|
235
|
-
end.
|
235
|
+
end.define_model do
|
236
236
|
belongs_to :imageable, polymorphic: true, dependent: :destroy
|
237
237
|
end
|
238
238
|
|
239
239
|
create_table(:users) do
|
240
|
-
end.
|
240
|
+
end.define_model do
|
241
241
|
has_one :image, as: :imageable
|
242
242
|
end
|
243
243
|
|
244
244
|
create_table(:companies) do
|
245
|
-
end.
|
245
|
+
end.define_model do
|
246
246
|
has_one :image, as: :imageable
|
247
247
|
end
|
248
248
|
|
249
249
|
assert_problems(<<~OUTPUT)
|
250
|
-
use `dependent: :delete` or similar on
|
250
|
+
use `dependent: :delete` or similar on TransientRecord::Models::Image.imageable - associated models TransientRecord::Models::Company, TransientRecord::Models::User have no callbacks and can be deleted without loading
|
251
251
|
OUTPUT
|
252
252
|
end
|
253
253
|
|
@@ -255,12 +255,12 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
255
255
|
create_table(:images) do |t|
|
256
256
|
t.bigint :imageable_id, null: false
|
257
257
|
t.string :imageable_type, null: true
|
258
|
-
end.
|
258
|
+
end.define_model do
|
259
259
|
belongs_to :imageable, polymorphic: true, dependent: :destroy
|
260
260
|
end
|
261
261
|
|
262
262
|
create_table(:users) do
|
263
|
-
end.
|
263
|
+
end.define_model do
|
264
264
|
has_one :image, as: :imageable
|
265
265
|
|
266
266
|
before_destroy :log
|
@@ -270,7 +270,7 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
270
270
|
end
|
271
271
|
|
272
272
|
create_table(:companies) do
|
273
|
-
end.
|
273
|
+
end.define_model do
|
274
274
|
has_one :image, as: :imageable
|
275
275
|
end
|
276
276
|
|
@@ -281,12 +281,12 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
281
281
|
create_table(:images) do |t|
|
282
282
|
t.bigint :imageable_id, null: false
|
283
283
|
t.string :imageable_type, null: true
|
284
|
-
end.
|
284
|
+
end.define_model do
|
285
285
|
belongs_to :imageable, polymorphic: true, dependent: :delete
|
286
286
|
end
|
287
287
|
|
288
288
|
create_table(:users) do
|
289
|
-
end.
|
289
|
+
end.define_model do
|
290
290
|
has_one :image, as: :imageable
|
291
291
|
|
292
292
|
before_destroy :log
|
@@ -296,12 +296,12 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
296
296
|
end
|
297
297
|
|
298
298
|
create_table(:companies) do
|
299
|
-
end.
|
299
|
+
end.define_model do
|
300
300
|
has_one :image, as: :imageable
|
301
301
|
end
|
302
302
|
|
303
303
|
assert_problems(<<~OUTPUT)
|
304
|
-
use `dependent: :destroy` or similar on
|
304
|
+
use `dependent: :destroy` or similar on TransientRecord::Models::Image.imageable - associated model TransientRecord::Models::User has callbacks that are currently skipped
|
305
305
|
OUTPUT
|
306
306
|
end
|
307
307
|
|
@@ -309,39 +309,157 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
309
309
|
create_table(:images) do |t|
|
310
310
|
t.bigint :imageable_id, null: false
|
311
311
|
t.string :imageable_type, null: true
|
312
|
-
end.
|
312
|
+
end.define_model do
|
313
313
|
belongs_to :imageable, polymorphic: true, dependent: :delete
|
314
314
|
end
|
315
315
|
|
316
316
|
create_table(:users) do
|
317
|
-
end.
|
317
|
+
end.define_model do
|
318
318
|
has_one :image, as: :imageable
|
319
319
|
end
|
320
320
|
|
321
321
|
create_table(:companies) do
|
322
|
-
end.
|
322
|
+
end.define_model do
|
323
323
|
has_one :image, as: :imageable
|
324
324
|
end
|
325
325
|
|
326
326
|
refute_problems
|
327
327
|
end
|
328
328
|
|
329
|
+
def test_works_on_has_through_associations_with_destroy
|
330
|
+
create_table(:users) do
|
331
|
+
end.define_model do
|
332
|
+
has_many :posts
|
333
|
+
has_many :comments, through: :posts, dependent: :destroy
|
334
|
+
end
|
335
|
+
|
336
|
+
create_table(:posts) do |t|
|
337
|
+
t.references :users
|
338
|
+
end.define_model do
|
339
|
+
belongs_to :user
|
340
|
+
has_many :comments
|
341
|
+
end
|
342
|
+
|
343
|
+
create_table(:comments) do |t|
|
344
|
+
t.references :posts
|
345
|
+
end.define_model do
|
346
|
+
belongs_to :post
|
347
|
+
end
|
348
|
+
|
349
|
+
assert_problems(<<~OUTPUT)
|
350
|
+
use `dependent: :delete_all` or similar on TransientRecord::Models::User.comments - associated join model TransientRecord::Models::Post has no callbacks and can be deleted in bulk
|
351
|
+
OUTPUT
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_works_on_has_through_associations_with_delete_all
|
355
|
+
create_table(:users) do
|
356
|
+
end.define_model do
|
357
|
+
has_many :posts
|
358
|
+
has_many :comments, through: :posts, dependent: :delete_all
|
359
|
+
end
|
360
|
+
|
361
|
+
create_table(:posts) do |t|
|
362
|
+
t.references :users
|
363
|
+
end.define_model do
|
364
|
+
belongs_to :user
|
365
|
+
has_many :comments
|
366
|
+
|
367
|
+
before_destroy :log
|
368
|
+
|
369
|
+
def log
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
create_table(:comments) do |t|
|
374
|
+
t.references :posts
|
375
|
+
end.define_model do
|
376
|
+
belongs_to :post
|
377
|
+
end
|
378
|
+
|
379
|
+
assert_problems(<<~OUTPUT)
|
380
|
+
use `dependent: :destroy` or similar on TransientRecord::Models::User.comments - associated join model TransientRecord::Models::Post has callbacks that are currently skipped
|
381
|
+
OUTPUT
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_has_through_associations_when_join_model_incomplete
|
385
|
+
create_table(:users) do
|
386
|
+
end.define_model do
|
387
|
+
has_many :posts
|
388
|
+
has_many :comments, through: :posts
|
389
|
+
end
|
390
|
+
|
391
|
+
create_table(:posts) do |t|
|
392
|
+
t.references :users
|
393
|
+
end.define_model do
|
394
|
+
# The join model should define has_many :comments, but intentionally skips
|
395
|
+
# it for this test case's purpose.
|
396
|
+
end
|
397
|
+
|
398
|
+
create_table(:comments) do |t|
|
399
|
+
t.references :posts
|
400
|
+
end.define_model do
|
401
|
+
end
|
402
|
+
|
403
|
+
assert_problems(<<~OUTPUT)
|
404
|
+
ensure TransientRecord::Models::User.comments is configured correctly - TransientRecord::Models::Post.comments may be undefined
|
405
|
+
OUTPUT
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_destroy_async_and_foreign_key_exists
|
409
|
+
skip("ActiveRecord < 6.1 doesn't support :destroy_async") if ActiveRecord::VERSION::STRING < "6.1"
|
410
|
+
|
411
|
+
create_table(:companies) do
|
412
|
+
end.define_model do
|
413
|
+
# We need an ActiveJob job defined to appease the ActiveRecord
|
414
|
+
class_attribute :destroy_association_async_job, default: Class.new
|
415
|
+
|
416
|
+
has_many :users, dependent: :destroy_async
|
417
|
+
end
|
418
|
+
|
419
|
+
create_table(:users) do |t|
|
420
|
+
t.references :company, foreign_key: true
|
421
|
+
end.define_model
|
422
|
+
|
423
|
+
assert_problems(<<~OUTPUT)
|
424
|
+
don't use `dependent: :destroy_async` on TransientRecord::Models::Company.users or remove the foreign key from users.company_id - \
|
425
|
+
associated models will be deleted in the same transaction along with TransientRecord::Models::Company
|
426
|
+
OUTPUT
|
427
|
+
end
|
428
|
+
|
429
|
+
def test_destroy_async_and_no_foreign_key
|
430
|
+
skip("ActiveRecord < 6.1 doesn't support :destroy_async") if ActiveRecord::VERSION::STRING < "6.1"
|
431
|
+
|
432
|
+
create_table(:companies) do
|
433
|
+
end.define_model do
|
434
|
+
# We need an ActiveJob job defined to appease the ActiveRecord
|
435
|
+
class_attribute :destroy_association_async_job, default: Class.new
|
436
|
+
|
437
|
+
has_many :users, dependent: :destroy_async
|
438
|
+
end
|
439
|
+
|
440
|
+
create_table(:users) do |t|
|
441
|
+
t.references :company, foreign_key: false
|
442
|
+
end.define_model
|
443
|
+
|
444
|
+
refute_problems
|
445
|
+
end
|
446
|
+
|
329
447
|
def test_config_ignore_models
|
330
448
|
create_table(:companies) do
|
331
|
-
end.
|
449
|
+
end.define_model do
|
332
450
|
has_many :users, dependent: :destroy
|
333
451
|
end
|
334
452
|
|
335
453
|
create_table(:users) do |t|
|
336
454
|
t.references :companies
|
337
|
-
end.
|
455
|
+
end.define_model do
|
338
456
|
belongs_to :company
|
339
457
|
end
|
340
458
|
|
341
459
|
config_file(<<-CONFIG)
|
342
460
|
ActiveRecordDoctor.configure do |config|
|
343
461
|
config.detector :incorrect_dependent_option,
|
344
|
-
ignore_models: ["
|
462
|
+
ignore_models: ["TransientRecord::Models::Company"]
|
345
463
|
end
|
346
464
|
CONFIG
|
347
465
|
|
@@ -350,19 +468,19 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
350
468
|
|
351
469
|
def test_global_ignore_models
|
352
470
|
create_table(:companies) do
|
353
|
-
end.
|
471
|
+
end.define_model do
|
354
472
|
has_many :users, dependent: :destroy
|
355
473
|
end
|
356
474
|
|
357
475
|
create_table(:users) do |t|
|
358
476
|
t.references :companies
|
359
|
-
end.
|
477
|
+
end.define_model do
|
360
478
|
belongs_to :company
|
361
479
|
end
|
362
480
|
|
363
481
|
config_file(<<-CONFIG)
|
364
482
|
ActiveRecordDoctor.configure do |config|
|
365
|
-
config.global :ignore_models, ["
|
483
|
+
config.global :ignore_models, ["TransientRecord::Models::Company"]
|
366
484
|
end
|
367
485
|
CONFIG
|
368
486
|
|
@@ -371,20 +489,20 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
|
|
371
489
|
|
372
490
|
def test_config_ignore_associations
|
373
491
|
create_table(:companies) do
|
374
|
-
end.
|
492
|
+
end.define_model do
|
375
493
|
has_many :users, dependent: :destroy
|
376
494
|
end
|
377
495
|
|
378
496
|
create_table(:users) do |t|
|
379
497
|
t.references :companies
|
380
|
-
end.
|
498
|
+
end.define_model do
|
381
499
|
belongs_to :company
|
382
500
|
end
|
383
501
|
|
384
502
|
config_file(<<-CONFIG)
|
385
503
|
ActiveRecordDoctor.configure do |config|
|
386
504
|
config.detector :incorrect_dependent_option,
|
387
|
-
ignore_associations: ["
|
505
|
+
ignore_associations: ["TransientRecord::Models::Company.users"]
|
388
506
|
end
|
389
507
|
CONFIG
|
390
508
|
|
@@ -4,8 +4,10 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
4
4
|
def test_validation_and_limit_equal_is_ok
|
5
5
|
create_table(:users) do |t|
|
6
6
|
t.string :email, limit: 64
|
7
|
-
|
7
|
+
t.string :name, limit: 32
|
8
|
+
end.define_model do
|
8
9
|
validates :email, length: { maximum: 64 }
|
10
|
+
validates :name, length: { maximum: 32 }
|
9
11
|
end
|
10
12
|
|
11
13
|
refute_problems
|
@@ -14,12 +16,12 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
14
16
|
def test_validation_and_limit_different_is_error
|
15
17
|
create_table(:users) do |t|
|
16
18
|
t.string :email, limit: 64
|
17
|
-
end.
|
19
|
+
end.define_model do
|
18
20
|
validates :email, length: { maximum: 32 }
|
19
21
|
end
|
20
22
|
|
21
23
|
assert_problems(<<~OUTPUT)
|
22
|
-
the schema limits users.email to 64 characters but the length validator on
|
24
|
+
the schema limits users.email to 64 characters but the length validator on TransientRecord::Models::User.email enforces a maximum of 32 characters - set both limits to the same value or remove both
|
23
25
|
OUTPUT
|
24
26
|
end
|
25
27
|
|
@@ -28,23 +30,23 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
28
30
|
|
29
31
|
create_table(:users) do |t|
|
30
32
|
t.string :email
|
31
|
-
end.
|
33
|
+
end.define_model do
|
32
34
|
validates :email, length: { maximum: 32 }
|
33
35
|
end
|
34
36
|
|
35
37
|
assert_problems(<<~OUTPUT)
|
36
|
-
the length validator on
|
38
|
+
the length validator on TransientRecord::Models::User.email enforces a maximum of 32 characters but there's no schema limit on users.email - remove the validator or the schema length limit
|
37
39
|
OUTPUT
|
38
40
|
end
|
39
41
|
|
40
42
|
def test_no_validation_and_limit_is_error
|
41
43
|
create_table(:users) do |t|
|
42
44
|
t.string :email, limit: 64
|
43
|
-
end.
|
45
|
+
end.define_model do
|
44
46
|
end
|
45
47
|
|
46
48
|
assert_problems(<<~OUTPUT)
|
47
|
-
the schema limits users.email to 64 characters but there's no length validator on
|
49
|
+
the schema limits users.email to 64 characters but there's no length validator on TransientRecord::Models::User.email - remove the database limit or add the validator
|
48
50
|
OUTPUT
|
49
51
|
end
|
50
52
|
|
@@ -53,7 +55,7 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
53
55
|
|
54
56
|
create_table(:users) do |t|
|
55
57
|
t.string :email
|
56
|
-
end.
|
58
|
+
end.define_model do
|
57
59
|
end
|
58
60
|
|
59
61
|
refute_problems
|
@@ -62,12 +64,12 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
62
64
|
def test_config_ignore_models
|
63
65
|
create_table(:users) do |t|
|
64
66
|
t.string :email, limit: 64
|
65
|
-
end.
|
67
|
+
end.define_model
|
66
68
|
|
67
69
|
config_file(<<-CONFIG)
|
68
70
|
ActiveRecordDoctor.configure do |config|
|
69
71
|
config.detector :incorrect_length_validation,
|
70
|
-
ignore_models: ["
|
72
|
+
ignore_models: ["TransientRecord::Models::User"]
|
71
73
|
end
|
72
74
|
CONFIG
|
73
75
|
|
@@ -77,11 +79,11 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
77
79
|
def test_global_ignore_models
|
78
80
|
create_table(:users) do |t|
|
79
81
|
t.string :email, limit: 64
|
80
|
-
end.
|
82
|
+
end.define_model
|
81
83
|
|
82
84
|
config_file(<<-CONFIG)
|
83
85
|
ActiveRecordDoctor.configure do |config|
|
84
|
-
config.global :ignore_models, ["
|
86
|
+
config.global :ignore_models, ["TransientRecord::Models::User"]
|
85
87
|
end
|
86
88
|
CONFIG
|
87
89
|
|
@@ -91,12 +93,12 @@ class ActiveRecordDoctor::Detectors::IncorrectLengthValidationTest < Minitest::T
|
|
91
93
|
def test_config_ignore_attributes
|
92
94
|
create_table(:users) do |t|
|
93
95
|
t.string :email, limit: 64
|
94
|
-
end.
|
96
|
+
end.define_model
|
95
97
|
|
96
98
|
config_file(<<-CONFIG)
|
97
99
|
ActiveRecordDoctor.configure do |config|
|
98
100
|
config.detector :incorrect_length_validation,
|
99
|
-
ignore_attributes: ["
|
101
|
+
ignore_attributes: ["TransientRecord::Models::User.email"]
|
100
102
|
end
|
101
103
|
CONFIG
|
102
104
|
|
@@ -11,7 +11,7 @@ class ActiveRecordDoctor::Detectors::MismatchedForeignKeyTypeTest < Minitest::Te
|
|
11
11
|
end
|
12
12
|
|
13
13
|
assert_problems(<<~OUTPUT)
|
14
|
-
users.company_id
|
14
|
+
users.company_id is a foreign key of type integer and references companies.id of type bigint - foreign keys should be of the same type as the referenced column
|
15
15
|
OUTPUT
|
16
16
|
end
|
17
17
|
|
@@ -24,6 +24,40 @@ class ActiveRecordDoctor::Detectors::MismatchedForeignKeyTypeTest < Minitest::Te
|
|
24
24
|
refute_problems
|
25
25
|
end
|
26
26
|
|
27
|
+
def test_mismatched_foreign_key_with_non_primary_key_type_is_reported
|
28
|
+
# MySQL does not allow foreign keys to have different type than paired primary keys
|
29
|
+
return if mysql?
|
30
|
+
|
31
|
+
create_table(:companies, id: :bigint) do |t|
|
32
|
+
t.string :code
|
33
|
+
t.index :code, unique: true
|
34
|
+
end
|
35
|
+
create_table(:users) do |t|
|
36
|
+
t.text :code
|
37
|
+
t.foreign_key :companies, table: :companies, column: :code, primary_key: :code
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_problems(<<~OUTPUT)
|
41
|
+
users.code is a foreign key of type text and references companies.code of type character varying - foreign keys should be of the same type as the referenced column
|
42
|
+
OUTPUT
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_matched_foreign_key_with_non_primary_key_type_is_not_reported
|
46
|
+
# MySQL does not allow foreign keys to have different type than paired primary keys
|
47
|
+
return if mysql?
|
48
|
+
|
49
|
+
create_table(:companies, id: :bigint) do |t|
|
50
|
+
t.string :code
|
51
|
+
t.index :code, unique: true
|
52
|
+
end
|
53
|
+
create_table(:users) do |t|
|
54
|
+
t.string :code
|
55
|
+
t.foreign_key :companies, table: :companies, column: :code, primary_key: :code
|
56
|
+
end
|
57
|
+
|
58
|
+
refute_problems
|
59
|
+
end
|
60
|
+
|
27
61
|
def test_config_ignore_tables
|
28
62
|
# MySQL does not allow foreign keys to have different type than paired primary keys
|
29
63
|
return if mysql?
|