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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -15
  3. data/lib/active_record_doctor/detectors/base.rb +194 -53
  4. data/lib/active_record_doctor/detectors/extraneous_indexes.rb +36 -34
  5. data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +2 -5
  6. data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +87 -37
  7. data/lib/active_record_doctor/detectors/incorrect_length_validation.rb +7 -10
  8. data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +16 -9
  9. data/lib/active_record_doctor/detectors/missing_foreign_keys.rb +2 -4
  10. data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +13 -11
  11. data/lib/active_record_doctor/detectors/missing_presence_validation.rb +14 -7
  12. data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +70 -35
  13. data/lib/active_record_doctor/detectors/short_primary_key_type.rb +4 -4
  14. data/lib/active_record_doctor/detectors/undefined_table_references.rb +2 -2
  15. data/lib/active_record_doctor/detectors/unindexed_deleted_at.rb +5 -13
  16. data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +35 -11
  17. data/lib/active_record_doctor/logger/dummy.rb +11 -0
  18. data/lib/active_record_doctor/logger/hierarchical.rb +22 -0
  19. data/lib/active_record_doctor/logger.rb +6 -0
  20. data/lib/active_record_doctor/rake/task.rb +10 -1
  21. data/lib/active_record_doctor/runner.rb +8 -3
  22. data/lib/active_record_doctor/utils.rb +21 -0
  23. data/lib/active_record_doctor/version.rb +1 -1
  24. data/lib/active_record_doctor.rb +5 -0
  25. data/lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb +14 -14
  26. data/test/active_record_doctor/detectors/disable_test.rb +1 -1
  27. data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +59 -6
  28. data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +7 -7
  29. data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +175 -57
  30. data/test/active_record_doctor/detectors/incorrect_length_validation_test.rb +16 -14
  31. data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +35 -1
  32. data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +46 -23
  33. data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +55 -27
  34. data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +216 -47
  35. data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +5 -0
  36. data/test/active_record_doctor/detectors/undefined_table_references_test.rb +11 -13
  37. data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +39 -1
  38. data/test/active_record_doctor/runner_test.rb +18 -19
  39. data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +16 -6
  40. data/test/setup.rb +10 -6
  41. metadata +23 -7
  42. 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.create_model do
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.create_model do
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 ModelFactory::Models::Company.users - associated model ModelFactory::Models::User has no validations and can be deleted in bulk
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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 ModelFactory::Models::Company.users - the associated model ModelFactory::Models::User has callbacks that are currently skipped
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.create_model do
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.create_model do
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.create_model do
86
- has_one :owner, class_name: "ModelFactory::Models::User", dependent: :destroy
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.create_model do
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 ModelFactory::Models::Company.owner - the associated model ModelFactory::Models::User has no callbacks and can be deleted without loading
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.create_model do
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.create_model do
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 ModelFactory::Models::User.company - the associated model ModelFactory::Models::Company has no callbacks and can be deleted without loading
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.create_model do
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.create_model do
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.create_model do
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 ModelFactory::Models::User.company - the associated model ModelFactory::Models::Company has no callbacks and can be deleted without loading
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.create_model do
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.create_model do
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.create_model do
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 ModelFactory::Models::User.company - the associated model ModelFactory::Models::Company has no callbacks and can be deleted without loading
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.create_model do
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.create_model do
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.create_model do
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 ModelFactory::Models::User.company - the associated model ModelFactory::Models::Company has callbacks that are currently skipped
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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 ModelFactory::Models::Image.imageable - the associated models ModelFactory::Models::Company, ModelFactory::Models::User have no callbacks and can be deleted without loading
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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 ModelFactory::Models::Image.imageable - the associated model ModelFactory::Models::User has callbacks that are currently skipped
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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.create_model do
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: ["ModelFactory::Models::Company"]
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.create_model do
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.create_model do
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, ["ModelFactory::Models::Company"]
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.create_model do
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.create_model do
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: ["ModelFactory::Models::Company.users"]
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
- end.create_model do
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.create_model do
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 ModelFactory::Models::User.email enforces a maximum of 32 characters - set both limits to the same value or remove both
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.create_model do
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 ModelFactory::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
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.create_model do
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 ModelFactory::Models::User.email - remove the database limit or add the validator
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.create_model do
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.create_model
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: ["ModelFactory::Models::User"]
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.create_model
82
+ end.define_model
81
83
 
82
84
  config_file(<<-CONFIG)
83
85
  ActiveRecordDoctor.configure do |config|
84
- config.global :ignore_models, ["ModelFactory::Models::User"]
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.create_model
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: ["ModelFactory::Models::User.email"]
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 references a column of different type - foreign keys should be of the same type as the referenced column
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?