active_record_doctor 1.12.0 → 1.13.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 +27 -0
- data/lib/active_record_doctor/config/loader.rb +1 -1
- data/lib/active_record_doctor/detectors/base.rb +11 -7
- data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +1 -1
- data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +9 -4
- data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +1 -1
- data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +2 -2
- data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +16 -7
- data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +1 -0
- data/lib/active_record_doctor/logger/hierarchical.rb +1 -1
- data/lib/active_record_doctor/railtie.rb +1 -1
- data/lib/active_record_doctor/runner.rb +1 -1
- data/lib/active_record_doctor/utils.rb +2 -2
- data/lib/active_record_doctor/version.rb +1 -1
- data/lib/tasks/active_record_doctor.rake +2 -2
- metadata +12 -49
- data/test/active_record_doctor/config/loader_test.rb +0 -120
- data/test/active_record_doctor/config_test.rb +0 -116
- data/test/active_record_doctor/detectors/disable_test.rb +0 -30
- data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +0 -277
- data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +0 -79
- data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +0 -511
- data/test/active_record_doctor/detectors/incorrect_length_validation_test.rb +0 -107
- data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +0 -116
- data/test/active_record_doctor/detectors/missing_foreign_keys_test.rb +0 -70
- data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +0 -273
- data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +0 -232
- data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +0 -496
- data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +0 -77
- data/test/active_record_doctor/detectors/undefined_table_references_test.rb +0 -55
- data/test/active_record_doctor/detectors/unindexed_deleted_at_test.rb +0 -177
- data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +0 -116
- data/test/active_record_doctor/runner_test.rb +0 -41
- data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +0 -141
- data/test/setup.rb +0 -124
@@ -1,496 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::MissingUniqueIndexesTest < Minitest::Test
|
4
|
-
def test_missing_unique_index
|
5
|
-
create_table(:users) do |t|
|
6
|
-
t.string :email
|
7
|
-
t.index :email
|
8
|
-
end.define_model do
|
9
|
-
validates :email, uniqueness: true
|
10
|
-
end
|
11
|
-
|
12
|
-
assert_problems(<<~OUTPUT)
|
13
|
-
add a unique index on users(email) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
14
|
-
OUTPUT
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_missing_unique_index_on_functional_index
|
18
|
-
skip if !(ActiveRecord::VERSION::STRING >= "5.0" && postgresql?)
|
19
|
-
|
20
|
-
create_table(:users) do |t|
|
21
|
-
t.string :email
|
22
|
-
t.index "lower(email)"
|
23
|
-
end.define_model do
|
24
|
-
validates :email, uniqueness: true
|
25
|
-
end
|
26
|
-
|
27
|
-
# Running the detector should NOT raise an error when a functional index
|
28
|
-
# is present. No need to assert anything -- the test is successful if no
|
29
|
-
# exception was raised.
|
30
|
-
run_detector
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_validates_multiple_attributes
|
34
|
-
create_table(:users) do |t|
|
35
|
-
t.string :email
|
36
|
-
t.string :ref_token
|
37
|
-
end.define_model do
|
38
|
-
validates :email, :ref_token, uniqueness: true
|
39
|
-
end
|
40
|
-
|
41
|
-
assert_problems(<<~OUTPUT)
|
42
|
-
add a unique index on users(email) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
43
|
-
add a unique index on users(ref_token) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
44
|
-
OUTPUT
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_present_unique_index
|
48
|
-
create_table(:users) do |t|
|
49
|
-
t.string :email
|
50
|
-
t.index :email, unique: true
|
51
|
-
end.define_model do
|
52
|
-
validates :email, uniqueness: true
|
53
|
-
end
|
54
|
-
|
55
|
-
refute_problems
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_missing_unique_index_reported_only_on_base_class
|
59
|
-
create_table(:users) do |t|
|
60
|
-
t.string :type
|
61
|
-
t.string :email
|
62
|
-
t.string :name
|
63
|
-
end.define_model do
|
64
|
-
validates :email, uniqueness: true
|
65
|
-
end
|
66
|
-
|
67
|
-
define_model(:Client, TransientRecord::Models::User) do
|
68
|
-
validates :name, uniqueness: true
|
69
|
-
end
|
70
|
-
|
71
|
-
assert_problems(<<~OUTPUT)
|
72
|
-
add a unique index on users(email) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
73
|
-
add a unique index on users(name) - validating uniqueness in TransientRecord::Models::Client without an index can lead to duplicates
|
74
|
-
OUTPUT
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_present_partial_unique_index
|
78
|
-
skip("MySQL doesn't support partial indexes") if mysql?
|
79
|
-
|
80
|
-
create_table(:users) do |t|
|
81
|
-
t.string :email
|
82
|
-
t.boolean :active
|
83
|
-
t.index :email, unique: true, where: "active"
|
84
|
-
end.define_model do
|
85
|
-
validates :email, uniqueness: true
|
86
|
-
end
|
87
|
-
|
88
|
-
assert_problems(<<~OUTPUT)
|
89
|
-
add a unique index on users(email) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
90
|
-
OUTPUT
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_unique_index_with_extra_columns_with_scope
|
94
|
-
create_table(:users) do |t|
|
95
|
-
t.string :email
|
96
|
-
t.integer :company_id
|
97
|
-
t.integer :department_id
|
98
|
-
t.index [:company_id, :department_id, :email]
|
99
|
-
end.define_model do
|
100
|
-
validates :email, uniqueness: { scope: [:company_id, :department_id] }
|
101
|
-
end
|
102
|
-
|
103
|
-
assert_problems(<<~OUTPUT)
|
104
|
-
add a unique index on users(company_id, department_id, email) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
105
|
-
OUTPUT
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_unique_index_with_exact_columns_with_scope
|
109
|
-
create_table(:users) do |t|
|
110
|
-
t.string :email
|
111
|
-
t.integer :company_id
|
112
|
-
t.integer :department_id
|
113
|
-
t.index [:company_id, :department_id, :email], unique: true
|
114
|
-
end.define_model do
|
115
|
-
validates :email, uniqueness: { scope: [:company_id, :department_id] }
|
116
|
-
end
|
117
|
-
|
118
|
-
refute_problems
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_unique_index_with_fewer_columns_with_scope
|
122
|
-
create_table(:users) do |t|
|
123
|
-
t.string :email
|
124
|
-
t.integer :company_id
|
125
|
-
t.integer :department_id
|
126
|
-
t.index [:company_id, :department_id], unique: true
|
127
|
-
end.define_model do
|
128
|
-
validates :email, uniqueness: { scope: [:company_id, :department_id] }
|
129
|
-
end
|
130
|
-
|
131
|
-
refute_problems
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_missing_unique_index_with_association_attribute
|
135
|
-
create_table(:users) do |t|
|
136
|
-
t.integer :account_id
|
137
|
-
end.define_model do
|
138
|
-
belongs_to :account
|
139
|
-
validates :account, uniqueness: true
|
140
|
-
end
|
141
|
-
|
142
|
-
assert_problems(<<~OUTPUT)
|
143
|
-
add a unique index on users(account_id) - validating uniqueness in TransientRecord::Models::User without an index can lead to duplicates
|
144
|
-
OUTPUT
|
145
|
-
end
|
146
|
-
|
147
|
-
def test_present_unique_index_with_association_attribute
|
148
|
-
create_table(:users) do |t|
|
149
|
-
t.integer :account_id
|
150
|
-
t.index :account_id, unique: true
|
151
|
-
end.define_model do
|
152
|
-
belongs_to :account
|
153
|
-
validates :account, uniqueness: true
|
154
|
-
end
|
155
|
-
|
156
|
-
refute_problems
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_missing_unique_index_with_association_scope
|
160
|
-
create_table(:comments) do |t|
|
161
|
-
t.string :title
|
162
|
-
t.integer :commentable_id
|
163
|
-
t.string :commentable_type
|
164
|
-
end.define_model do
|
165
|
-
belongs_to :commentable, polymorphic: true
|
166
|
-
validates :title, uniqueness: { scope: :commentable }
|
167
|
-
end
|
168
|
-
|
169
|
-
assert_problems(<<~OUTPUT)
|
170
|
-
add a unique index on comments(commentable_type, commentable_id, title) - validating uniqueness in TransientRecord::Models::Comment without an index can lead to duplicates
|
171
|
-
OUTPUT
|
172
|
-
end
|
173
|
-
|
174
|
-
def test_present_unique_index_with_association_scope
|
175
|
-
create_table(:comments) do |t|
|
176
|
-
t.string :title
|
177
|
-
t.integer :commentable_id
|
178
|
-
t.string :commentable_type
|
179
|
-
t.index [:commentable_id, :commentable_type, :title], unique: true
|
180
|
-
end.define_model do
|
181
|
-
belongs_to :commentable, polymorphic: true
|
182
|
-
validates :title, uniqueness: { scope: :commentable }
|
183
|
-
end
|
184
|
-
|
185
|
-
refute_problems
|
186
|
-
end
|
187
|
-
|
188
|
-
def test_column_order_is_ignored
|
189
|
-
create_table(:users) do |t|
|
190
|
-
t.string :email
|
191
|
-
t.integer :organization_id
|
192
|
-
|
193
|
-
t.index [:email, :organization_id], unique: true
|
194
|
-
end.define_model do
|
195
|
-
validates :email, uniqueness: { scope: :organization_id }
|
196
|
-
end
|
197
|
-
|
198
|
-
refute_problems
|
199
|
-
end
|
200
|
-
|
201
|
-
def test_case_insensitive_unique_index_exists
|
202
|
-
skip("Expression indexes are not supported") if ActiveRecordDoctor::Utils.expression_indexes_unsupported?
|
203
|
-
|
204
|
-
create_table(:users) do |t|
|
205
|
-
t.string :email
|
206
|
-
|
207
|
-
t.index :email, unique: true
|
208
|
-
end.define_model do
|
209
|
-
validates :email, uniqueness: { case_sensitive: false }
|
210
|
-
end
|
211
|
-
|
212
|
-
assert_problems(<<~OUTPUT)
|
213
|
-
add a unique expression index on users(lower(email)) - validating case-insensitive uniqueness in TransientRecord::Models::User without an expression index can lead to duplicates (a regular unique index is not enough)
|
214
|
-
OUTPUT
|
215
|
-
end
|
216
|
-
|
217
|
-
def test_case_insensitive_non_unique_lower_index_exists
|
218
|
-
skip("Expression indexes are not supported") if ActiveRecordDoctor::Utils.expression_indexes_unsupported?
|
219
|
-
|
220
|
-
create_table(:users) do |t|
|
221
|
-
t.string :email
|
222
|
-
end.define_model do
|
223
|
-
validates :email, uniqueness: { case_sensitive: false }
|
224
|
-
end
|
225
|
-
|
226
|
-
# ActiveRecord < 5 does not support expression indexes.
|
227
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
228
|
-
CREATE INDEX index_users_on_lower_email ON users ((lower(email)))
|
229
|
-
SQL
|
230
|
-
|
231
|
-
assert_problems(<<~OUTPUT)
|
232
|
-
add a unique expression index on users(lower(email)) - validating case-insensitive uniqueness in TransientRecord::Models::User without an expression index can lead to duplicates (a regular unique index is not enough)
|
233
|
-
OUTPUT
|
234
|
-
end
|
235
|
-
|
236
|
-
def test_case_insensitive_unique_lower_index_exists
|
237
|
-
skip("Expression indexes are not supported") if ActiveRecordDoctor::Utils.expression_indexes_unsupported?
|
238
|
-
|
239
|
-
create_table(:users) do |t|
|
240
|
-
t.string :email
|
241
|
-
end.define_model do
|
242
|
-
validates :email, uniqueness: { case_sensitive: false }
|
243
|
-
end
|
244
|
-
|
245
|
-
# ActiveRecord < 5 does not support expression indexes.
|
246
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
247
|
-
CREATE UNIQUE INDEX index_users_on_lower_email ON users ((lower(email)))
|
248
|
-
SQL
|
249
|
-
|
250
|
-
refute_problems
|
251
|
-
end
|
252
|
-
|
253
|
-
def test_case_insensitive_compound_unique_index_exists
|
254
|
-
skip("Expression indexes are not supported") if ActiveRecordDoctor::Utils.expression_indexes_unsupported?
|
255
|
-
|
256
|
-
create_table(:users) do |t|
|
257
|
-
t.string :email
|
258
|
-
t.integer :organization_id
|
259
|
-
t.index [:email, :organization_id], unique: true
|
260
|
-
end.define_model do
|
261
|
-
validates :email, uniqueness: { scope: :organization_id, case_sensitive: false }
|
262
|
-
end
|
263
|
-
|
264
|
-
assert_problems(<<~OUTPUT)
|
265
|
-
add a unique expression index on users(organization_id, lower(email)) - validating case-insensitive uniqueness in TransientRecord::Models::User without an expression index can lead to duplicates (a regular unique index is not enough)
|
266
|
-
OUTPUT
|
267
|
-
end
|
268
|
-
|
269
|
-
def test_case_insensitive_compound_non_unique_lower_index_exists
|
270
|
-
skip("Expression indexes are not supported") if ActiveRecordDoctor::Utils.expression_indexes_unsupported?
|
271
|
-
|
272
|
-
create_table(:users) do |t|
|
273
|
-
t.string :email
|
274
|
-
t.integer :organization_id
|
275
|
-
end.define_model do
|
276
|
-
validates :email, uniqueness: { scope: :organization_id, case_sensitive: false }
|
277
|
-
end
|
278
|
-
|
279
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
280
|
-
CREATE INDEX index_users_on_lower_email_and_organization_id ON users ((lower(email)), organization_id)
|
281
|
-
SQL
|
282
|
-
|
283
|
-
assert_problems(<<~OUTPUT)
|
284
|
-
add a unique expression index on users(organization_id, lower(email)) - validating case-insensitive uniqueness in TransientRecord::Models::User without an expression index can lead to duplicates (a regular unique index is not enough)
|
285
|
-
OUTPUT
|
286
|
-
end
|
287
|
-
|
288
|
-
def test_case_insensitive_compound_unique_lower_index_exists
|
289
|
-
skip("Expression indexes are not supported") if ActiveRecordDoctor::Utils.expression_indexes_unsupported?
|
290
|
-
|
291
|
-
create_table(:users) do |t|
|
292
|
-
t.string :email
|
293
|
-
t.integer :organization_id
|
294
|
-
end.define_model do
|
295
|
-
validates :email, uniqueness: { scope: :organization_id, case_sensitive: false }
|
296
|
-
end
|
297
|
-
|
298
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
299
|
-
CREATE UNIQUE INDEX index_users_on_lower_email_and_organization_id ON users ((lower(email)), organization_id)
|
300
|
-
SQL
|
301
|
-
|
302
|
-
refute_problems
|
303
|
-
end
|
304
|
-
|
305
|
-
def test_conditions_is_skipped
|
306
|
-
assert_skipped(conditions: -> { where.not(email: nil) })
|
307
|
-
end
|
308
|
-
|
309
|
-
def test_if_is_skipped
|
310
|
-
assert_skipped(if: ->(_model) { true })
|
311
|
-
end
|
312
|
-
|
313
|
-
def test_unless_is_skipped
|
314
|
-
assert_skipped(unless: ->(_model) { true })
|
315
|
-
end
|
316
|
-
|
317
|
-
def test_skips_validator_without_attributes
|
318
|
-
create_table(:users) do |t|
|
319
|
-
t.string :email
|
320
|
-
t.index :email
|
321
|
-
end.define_model do
|
322
|
-
validates_with DummyValidator
|
323
|
-
end
|
324
|
-
|
325
|
-
refute_problems
|
326
|
-
end
|
327
|
-
|
328
|
-
def test_has_one_without_index
|
329
|
-
create_table(:users)
|
330
|
-
.define_model do
|
331
|
-
has_one :account, class_name: "TransientRecord::Models::Account"
|
332
|
-
has_one :account_history, through: :account, class_name: "TransientRecord::Models::Account"
|
333
|
-
end
|
334
|
-
|
335
|
-
create_table(:accounts) do |t|
|
336
|
-
t.integer :user_id
|
337
|
-
end.define_model do
|
338
|
-
has_one :account_history, class_name: "TransientRecord::Models::AccountHistory"
|
339
|
-
end
|
340
|
-
|
341
|
-
create_table(:account_histories) do |t|
|
342
|
-
t.integer :account_id
|
343
|
-
end.define_model do
|
344
|
-
belongs_to :account, class_name: "TransientRecord::Models::Account"
|
345
|
-
end
|
346
|
-
|
347
|
-
assert_problems(<<~OUTPUT)
|
348
|
-
add a unique index on accounts(user_id) - using `has_one` in TransientRecord::Models::User without an index can lead to duplicates
|
349
|
-
add a unique index on account_histories(account_id) - using `has_one` in TransientRecord::Models::Account without an index can lead to duplicates
|
350
|
-
OUTPUT
|
351
|
-
end
|
352
|
-
|
353
|
-
def test_has_one_with_scope_and_without_index
|
354
|
-
create_table(:users)
|
355
|
-
.define_model do
|
356
|
-
has_one :last_comment, -> { order(created_at: :desc) }, class_name: "TransientRecord::Models::Comment"
|
357
|
-
end
|
358
|
-
|
359
|
-
create_table(:comments) do |t|
|
360
|
-
t.integer :user_id
|
361
|
-
end.define_model
|
362
|
-
|
363
|
-
refute_problems
|
364
|
-
end
|
365
|
-
|
366
|
-
def test_missing_has_one_unique_index_reported_only_on_base_class
|
367
|
-
create_table(:users) do |t|
|
368
|
-
t.string :type
|
369
|
-
end.define_model do
|
370
|
-
has_one :account, class_name: "TransientRecord::Models::Account"
|
371
|
-
end
|
372
|
-
|
373
|
-
define_model(:Client, TransientRecord::Models::User)
|
374
|
-
|
375
|
-
create_table(:accounts) do |t|
|
376
|
-
t.integer :user_id
|
377
|
-
end.define_model
|
378
|
-
|
379
|
-
assert_problems(<<~OUTPUT)
|
380
|
-
add a unique index on accounts(user_id) - using `has_one` in TransientRecord::Models::User without an index can lead to duplicates
|
381
|
-
OUTPUT
|
382
|
-
end
|
383
|
-
|
384
|
-
def test_has_one_with_index
|
385
|
-
create_table(:users)
|
386
|
-
.define_model do
|
387
|
-
has_one :account, class_name: "TransientRecord::Models::Account"
|
388
|
-
end
|
389
|
-
|
390
|
-
create_table(:accounts) do |t|
|
391
|
-
t.integer :user_id, index: { unique: true }
|
392
|
-
end.define_model
|
393
|
-
|
394
|
-
refute_problems
|
395
|
-
end
|
396
|
-
|
397
|
-
def test_polymorphic_has_one_without_index
|
398
|
-
create_table(:users)
|
399
|
-
.define_model do
|
400
|
-
has_one :account, as: :accountable
|
401
|
-
end
|
402
|
-
|
403
|
-
create_table(:accounts) do |t|
|
404
|
-
t.belongs_to :accountable, polymorphic: true, index: false
|
405
|
-
end.define_model do
|
406
|
-
belongs_to :accountable, polymorphic: true
|
407
|
-
end
|
408
|
-
|
409
|
-
assert_problems(<<~OUTPUT)
|
410
|
-
add a unique index on accounts(accountable_type, accountable_id) - using `has_one` in TransientRecord::Models::User without an index can lead to duplicates
|
411
|
-
OUTPUT
|
412
|
-
end
|
413
|
-
|
414
|
-
def test_polymorphic_has_one_with_index
|
415
|
-
create_table(:users)
|
416
|
-
.define_model do
|
417
|
-
has_one :account, as: :accountable
|
418
|
-
end
|
419
|
-
|
420
|
-
create_table(:accounts) do |t|
|
421
|
-
t.belongs_to :accountable, polymorphic: true, index: { unique: true }
|
422
|
-
end.define_model do
|
423
|
-
belongs_to :accountable, polymorphic: true
|
424
|
-
end
|
425
|
-
|
426
|
-
refute_problems
|
427
|
-
end
|
428
|
-
|
429
|
-
def test_config_ignore_models
|
430
|
-
create_table(:users) do |t|
|
431
|
-
t.string :email
|
432
|
-
end.define_model do
|
433
|
-
validates :email, uniqueness: true
|
434
|
-
end
|
435
|
-
|
436
|
-
config_file(<<-CONFIG)
|
437
|
-
ActiveRecordDoctor.configure do |config|
|
438
|
-
config.detector :missing_unique_indexes,
|
439
|
-
ignore_models: ["TransientRecord::Models::User"]
|
440
|
-
end
|
441
|
-
CONFIG
|
442
|
-
|
443
|
-
refute_problems
|
444
|
-
end
|
445
|
-
|
446
|
-
def test_global_ignore_models
|
447
|
-
create_table(:users) do |t|
|
448
|
-
t.string :email
|
449
|
-
end.define_model do
|
450
|
-
validates :email, uniqueness: true
|
451
|
-
end
|
452
|
-
|
453
|
-
config_file(<<-CONFIG)
|
454
|
-
ActiveRecordDoctor.configure do |config|
|
455
|
-
config.global :ignore_models, ["TransientRecord::Models::User"]
|
456
|
-
end
|
457
|
-
CONFIG
|
458
|
-
|
459
|
-
refute_problems
|
460
|
-
end
|
461
|
-
|
462
|
-
def test_config_ignore_columns
|
463
|
-
create_table(:users) do |t|
|
464
|
-
t.string :email
|
465
|
-
t.integer :role
|
466
|
-
end.define_model do
|
467
|
-
validates :email, :role, uniqueness: { scope: :organization_id }
|
468
|
-
end
|
469
|
-
|
470
|
-
config_file(<<-CONFIG)
|
471
|
-
ActiveRecordDoctor.configure do |config|
|
472
|
-
config.detector :missing_unique_indexes,
|
473
|
-
ignore_columns: ["TransientRecord::Models::User(organization_id, email)", "TransientRecord::Models::User(organization_id, role)"]
|
474
|
-
end
|
475
|
-
CONFIG
|
476
|
-
|
477
|
-
refute_problems
|
478
|
-
end
|
479
|
-
|
480
|
-
class DummyValidator < ActiveModel::Validator
|
481
|
-
def validate(record)
|
482
|
-
end
|
483
|
-
end
|
484
|
-
|
485
|
-
private
|
486
|
-
|
487
|
-
def assert_skipped(options)
|
488
|
-
create_table(:users) do |t|
|
489
|
-
t.string :email
|
490
|
-
end.define_model do
|
491
|
-
validates :email, uniqueness: options
|
492
|
-
end
|
493
|
-
|
494
|
-
refute_problems
|
495
|
-
end
|
496
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::ShortPrimaryKeyTypeTest < Minitest::Test
|
4
|
-
def setup
|
5
|
-
@connection = ActiveRecord::Base.connection
|
6
|
-
@connection.enable_extension("uuid-ossp") if postgresql?
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
|
-
def teardown
|
11
|
-
@connection.disable_extension("uuid-ossp") if postgresql?
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_short_integer_primary_key_is_reported
|
16
|
-
create_table(:companies, id: :int)
|
17
|
-
|
18
|
-
# In Rails 4.2 and MySQL primary key is not created due to a bug
|
19
|
-
if mysql? && ActiveRecord::VERSION::STRING < "5.0"
|
20
|
-
@connection.execute("ALTER TABLE companies ADD PRIMARY KEY(id)")
|
21
|
-
end
|
22
|
-
|
23
|
-
assert_problems(<<~OUTPUT)
|
24
|
-
change the type of companies.id to bigint
|
25
|
-
OUTPUT
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_non_integer_and_non_uuid_primary_key_is_not_reported
|
29
|
-
create_table(:companies, id: :string, primary_key: :uuid)
|
30
|
-
refute_problems
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_long_integer_primary_key_is_not_reported
|
34
|
-
create_table(:companies, id: :bigint)
|
35
|
-
refute_problems
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_uuid_primary_key_is_not_reported
|
39
|
-
skip unless postgresql?
|
40
|
-
|
41
|
-
create_table(:companies, id: :uuid)
|
42
|
-
refute_problems
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_no_primary_key_is_not_reported
|
46
|
-
create_table(:companies, id: false) do |t|
|
47
|
-
t.string :name, null: false
|
48
|
-
end
|
49
|
-
|
50
|
-
refute_problems
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_config_ignore_tables
|
54
|
-
create_table(:companies, id: :integer)
|
55
|
-
|
56
|
-
config_file(<<-CONFIG)
|
57
|
-
ActiveRecordDoctor.configure do |config|
|
58
|
-
config.detector :short_primary_key_type,
|
59
|
-
ignore_tables: ["companies"]
|
60
|
-
end
|
61
|
-
CONFIG
|
62
|
-
|
63
|
-
refute_problems
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_global_ignore_tables
|
67
|
-
create_table(:companies, id: :integer)
|
68
|
-
|
69
|
-
config_file(<<-CONFIG)
|
70
|
-
ActiveRecordDoctor.configure do |config|
|
71
|
-
config.global :ignore_tables, ["companies"]
|
72
|
-
end
|
73
|
-
CONFIG
|
74
|
-
|
75
|
-
refute_problems
|
76
|
-
end
|
77
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::UndefinedTableReferencesTest < Minitest::Test
|
4
|
-
def test_model_backed_by_table
|
5
|
-
create_table(:users) do
|
6
|
-
end.define_model do
|
7
|
-
end
|
8
|
-
|
9
|
-
refute_problems
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_model_backed_by_non_existent_table
|
13
|
-
define_model(:User)
|
14
|
-
|
15
|
-
assert_problems(<<~OUTPUT)
|
16
|
-
TransientRecord::Models::User references a non-existent table or view named users
|
17
|
-
OUTPUT
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_model_backed_by_view
|
21
|
-
# We replace the underlying table with a view. The view doesn't have to be
|
22
|
-
# backed by an actual table - it can simply return a predefined tuple.
|
23
|
-
ActiveRecord::Base.connection.execute("CREATE VIEW users AS SELECT 1")
|
24
|
-
define_model(:User)
|
25
|
-
|
26
|
-
refute_problems
|
27
|
-
ensure
|
28
|
-
ActiveRecord::Base.connection.execute("DROP VIEW users")
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_config_ignore_tables
|
32
|
-
define_model(:User)
|
33
|
-
|
34
|
-
config_file(<<-CONFIG)
|
35
|
-
ActiveRecordDoctor.configure do |config|
|
36
|
-
config.detector :undefined_table_references,
|
37
|
-
ignore_models: ["TransientRecord::Models::User"]
|
38
|
-
end
|
39
|
-
CONFIG
|
40
|
-
|
41
|
-
refute_problems
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_global_ignore_tables
|
45
|
-
define_model(:User)
|
46
|
-
|
47
|
-
config_file(<<-CONFIG)
|
48
|
-
ActiveRecordDoctor.configure do |config|
|
49
|
-
config.global :ignore_models, ["TransientRecord::Models::User"]
|
50
|
-
end
|
51
|
-
CONFIG
|
52
|
-
|
53
|
-
refute_problems
|
54
|
-
end
|
55
|
-
end
|