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,116 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::MismatchedForeignKeyTypeTest < Minitest::Test
|
4
|
-
def test_mismatched_foreign_key_type_is_reported
|
5
|
-
# MySQL does not allow foreign keys to have different type than paired primary keys
|
6
|
-
return if mysql?
|
7
|
-
|
8
|
-
create_table(:companies, id: :bigint)
|
9
|
-
create_table(:users) do |t|
|
10
|
-
t.references :company, foreign_key: true, type: :integer
|
11
|
-
end
|
12
|
-
|
13
|
-
assert_problems(<<~OUTPUT)
|
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
|
-
OUTPUT
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_matched_foreign_key_type_is_not_reported
|
19
|
-
create_table(:companies)
|
20
|
-
create_table(:users) do |t|
|
21
|
-
t.references :company, foreign_key: true
|
22
|
-
end
|
23
|
-
|
24
|
-
refute_problems
|
25
|
-
end
|
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
|
-
|
61
|
-
def test_config_ignore_tables
|
62
|
-
# MySQL does not allow foreign keys to have different type than paired primary keys
|
63
|
-
return if mysql?
|
64
|
-
|
65
|
-
create_table(:companies, id: :bigint)
|
66
|
-
create_table(:users) do |t|
|
67
|
-
t.references :company, foreign_key: true, type: :integer
|
68
|
-
end
|
69
|
-
|
70
|
-
config_file(<<-CONFIG)
|
71
|
-
ActiveRecordDoctor.configure do |config|
|
72
|
-
config.detector :mismatched_foreign_key_type,
|
73
|
-
ignore_tables: ["users"]
|
74
|
-
end
|
75
|
-
CONFIG
|
76
|
-
|
77
|
-
refute_problems
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_global_ignore_tables
|
81
|
-
# MySQL does not allow foreign keys to have different type than paired primary keys
|
82
|
-
return if mysql?
|
83
|
-
|
84
|
-
create_table(:companies, id: :bigint)
|
85
|
-
create_table(:users) do |t|
|
86
|
-
t.references :company, foreign_key: true, type: :integer
|
87
|
-
end
|
88
|
-
|
89
|
-
config_file(<<-CONFIG)
|
90
|
-
ActiveRecordDoctor.configure do |config|
|
91
|
-
config.global :ignore_tables, ["users"]
|
92
|
-
end
|
93
|
-
CONFIG
|
94
|
-
|
95
|
-
refute_problems
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_config_ignore_columns
|
99
|
-
# MySQL does not allow foreign keys to have different type than paired primary keys
|
100
|
-
return if mysql?
|
101
|
-
|
102
|
-
create_table(:companies, id: :bigint)
|
103
|
-
create_table(:users) do |t|
|
104
|
-
t.references :company, foreign_key: true, type: :integer
|
105
|
-
end
|
106
|
-
|
107
|
-
config_file(<<-CONFIG)
|
108
|
-
ActiveRecordDoctor.configure do |config|
|
109
|
-
config.detector :mismatched_foreign_key_type,
|
110
|
-
ignore_columns: ["users.company_id"]
|
111
|
-
end
|
112
|
-
CONFIG
|
113
|
-
|
114
|
-
refute_problems
|
115
|
-
end
|
116
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::MissingForeignKeysTest < Minitest::Test
|
4
|
-
def test_missing_foreign_key_is_reported
|
5
|
-
create_table(:companies)
|
6
|
-
create_table(:users) do |t|
|
7
|
-
t.references :company, foreign_key: false
|
8
|
-
end
|
9
|
-
|
10
|
-
assert_problems(<<~OUTPUT)
|
11
|
-
create a foreign key on users.company_id - looks like an association without a foreign key constraint
|
12
|
-
OUTPUT
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_present_foreign_key_is_not_reported
|
16
|
-
create_table(:companies)
|
17
|
-
create_table(:users) do |t|
|
18
|
-
t.references :company, foreign_key: true
|
19
|
-
end
|
20
|
-
|
21
|
-
refute_problems
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_config_ignore_models
|
25
|
-
create_table(:companies)
|
26
|
-
create_table(:users) do |t|
|
27
|
-
t.references :company, foreign_key: false
|
28
|
-
end
|
29
|
-
|
30
|
-
config_file(<<-CONFIG)
|
31
|
-
ActiveRecordDoctor.configure do |config|
|
32
|
-
config.detector :missing_foreign_keys,
|
33
|
-
ignore_tables: ["users"]
|
34
|
-
end
|
35
|
-
CONFIG
|
36
|
-
|
37
|
-
refute_problems
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_global_ignore_models
|
41
|
-
create_table(:companies)
|
42
|
-
create_table(:users) do |t|
|
43
|
-
t.references :company, foreign_key: false
|
44
|
-
end
|
45
|
-
|
46
|
-
config_file(<<-CONFIG)
|
47
|
-
ActiveRecordDoctor.configure do |config|
|
48
|
-
config.global :ignore_tables, ["users"]
|
49
|
-
end
|
50
|
-
CONFIG
|
51
|
-
|
52
|
-
refute_problems
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_config_ignore_columns
|
56
|
-
create_table(:companies)
|
57
|
-
create_table(:users) do |t|
|
58
|
-
t.references :company, foreign_key: false
|
59
|
-
end
|
60
|
-
|
61
|
-
config_file(<<-CONFIG)
|
62
|
-
ActiveRecordDoctor.configure do |config|
|
63
|
-
config.detector :missing_foreign_keys,
|
64
|
-
ignore_columns: ["users.company_id"]
|
65
|
-
end
|
66
|
-
CONFIG
|
67
|
-
|
68
|
-
refute_problems
|
69
|
-
end
|
70
|
-
end
|
@@ -1,273 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::MissingNonNullConstraintTest < Minitest::Test
|
4
|
-
def test_optional_columns_with_presence_validator_are_disallowed
|
5
|
-
create_table(:users) do |t|
|
6
|
-
t.string :name, null: true
|
7
|
-
end.define_model do
|
8
|
-
validates :name, presence: true
|
9
|
-
end
|
10
|
-
|
11
|
-
assert_problems(<<~OUTPUT)
|
12
|
-
add `NOT NULL` to users.name - models validates its presence but it's not non-NULL in the database
|
13
|
-
OUTPUT
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_optional_foreign_keys_with_required_association_are_disallowed
|
17
|
-
create_table(:companies)
|
18
|
-
create_table(:users) do |t|
|
19
|
-
t.references :company, null: true
|
20
|
-
end.define_model do
|
21
|
-
belongs_to :company, required: true
|
22
|
-
end
|
23
|
-
|
24
|
-
assert_problems(<<~OUTPUT)
|
25
|
-
add `NOT NULL` to users.company_id - models validates its presence but it's not non-NULL in the database
|
26
|
-
OUTPUT
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_optional_columns_with_required_polymorphic_association_are_disallowed
|
30
|
-
create_table(:comments) do |t|
|
31
|
-
t.references :commentable, polymorphic: true, null: true
|
32
|
-
end.define_model do
|
33
|
-
belongs_to :commentable, polymorphic: true, required: true
|
34
|
-
end
|
35
|
-
|
36
|
-
assert_problems(<<~OUTPUT)
|
37
|
-
add `NOT NULL` to comments.commentable_id - models validates its presence but it's not non-NULL in the database
|
38
|
-
add `NOT NULL` to comments.commentable_type - models validates its presence but it's not non-NULL in the database
|
39
|
-
OUTPUT
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_required_columns_with_required_polymorphic_association_are_allowed
|
43
|
-
create_table(:comments) do |t|
|
44
|
-
t.references :commentable, polymorphic: true, null: false
|
45
|
-
end.define_model do
|
46
|
-
belongs_to :commentable, polymorphic: true, required: true
|
47
|
-
end
|
48
|
-
|
49
|
-
refute_problems
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_required_columns_with_presence_validators_are_allowed
|
53
|
-
create_table(:users) do |t|
|
54
|
-
t.string :name, null: false
|
55
|
-
end.define_model do
|
56
|
-
validates :name, presence: true
|
57
|
-
end
|
58
|
-
|
59
|
-
refute_problems
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_optional_columns_without_presence_validator_are_allowed
|
63
|
-
create_table(:users) do |t|
|
64
|
-
t.string :name, null: false
|
65
|
-
end.define_model do
|
66
|
-
validates :name, presence: false
|
67
|
-
end
|
68
|
-
|
69
|
-
refute_problems
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_validators_matched_to_correct_columns
|
73
|
-
create_table(:users) do |t|
|
74
|
-
t.string :name, null: true
|
75
|
-
end.define_model do
|
76
|
-
# The age validator is a form of regression test against a bug that
|
77
|
-
# caused false positives. In this test case, name is NOT validated
|
78
|
-
# for presence so it does NOT need be marked non-NULL. However, the
|
79
|
-
# bug would match the age presence validator with the NULL-able name
|
80
|
-
# column which would result in a false positive error report.
|
81
|
-
validates :age, presence: true
|
82
|
-
validates :name, presence: false
|
83
|
-
end
|
84
|
-
|
85
|
-
refute_problems
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_validators_with_if_on_optional_columns_are_allowed
|
89
|
-
create_table(:users) do |t|
|
90
|
-
t.string :name, null: true
|
91
|
-
end.define_model do
|
92
|
-
validates :name, presence: true, if: -> { false }
|
93
|
-
end
|
94
|
-
|
95
|
-
refute_problems
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_validators_with_unless_on_optional_columns_are_allowed
|
99
|
-
create_table(:users) do |t|
|
100
|
-
t.string :name, null: true
|
101
|
-
end.define_model do
|
102
|
-
validates :name, presence: true, unless: -> { false }
|
103
|
-
end
|
104
|
-
|
105
|
-
refute_problems
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_validators_allowing_nil_on_optional_columns_are_allowed
|
109
|
-
create_table(:users) do |t|
|
110
|
-
t.string :name, null: true
|
111
|
-
end.define_model do
|
112
|
-
validates :name, presence: true, allow_nil: true
|
113
|
-
end
|
114
|
-
|
115
|
-
refute_problems
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_models_with_non_existent_tables_are_skipped
|
119
|
-
define_model(:User)
|
120
|
-
|
121
|
-
refute_problems
|
122
|
-
end
|
123
|
-
|
124
|
-
def test_optional_columns_validated_by_all_sti_models_are_disallowed
|
125
|
-
create_table(:users) do |t|
|
126
|
-
t.string :type, null: false
|
127
|
-
t.string :email, null: true
|
128
|
-
end.define_model
|
129
|
-
|
130
|
-
define_model(:Client, TransientRecord::Models::User) do
|
131
|
-
validates :email, presence: true
|
132
|
-
end
|
133
|
-
|
134
|
-
assert_problems(<<~OUTPUT)
|
135
|
-
add `NOT NULL` to users.email - models validates its presence but it's not non-NULL in the database
|
136
|
-
OUTPUT
|
137
|
-
end
|
138
|
-
|
139
|
-
def test_optional_columns_validated_by_some_sti_models_are_allowed
|
140
|
-
create_table(:users) do |t|
|
141
|
-
t.string :type, null: false
|
142
|
-
t.string :email, null: true
|
143
|
-
end.define_model
|
144
|
-
|
145
|
-
define_model(:Client, TransientRecord::Models::User) do
|
146
|
-
validates :email, presence: true
|
147
|
-
end
|
148
|
-
|
149
|
-
define_model(:Admin, TransientRecord::Models::User) do
|
150
|
-
validates :email, presence: false
|
151
|
-
end
|
152
|
-
|
153
|
-
refute_problems
|
154
|
-
end
|
155
|
-
|
156
|
-
def test_optional_columns_validated_by_all_non_sti_models_are_disallowed
|
157
|
-
create_table(:users) do |t|
|
158
|
-
t.string :email, null: true
|
159
|
-
end.define_model do
|
160
|
-
validates :email, presence: true
|
161
|
-
end
|
162
|
-
|
163
|
-
define_model(:Client) do
|
164
|
-
self.table_name = :users
|
165
|
-
|
166
|
-
validates :email, presence: true
|
167
|
-
end
|
168
|
-
|
169
|
-
assert_problems(<<~OUTPUT)
|
170
|
-
add `NOT NULL` to users.email - models validates its presence but it's not non-NULL in the database
|
171
|
-
OUTPUT
|
172
|
-
end
|
173
|
-
|
174
|
-
def test_optional_columns_validated_by_some_non_sti_models_are_allowed
|
175
|
-
create_table(:users) do |t|
|
176
|
-
t.string :email, null: true
|
177
|
-
end.define_model do
|
178
|
-
validates :email, presence: true
|
179
|
-
end
|
180
|
-
|
181
|
-
define_model(:Client) do
|
182
|
-
self.table_name = :users
|
183
|
-
|
184
|
-
validates :email, presence: false
|
185
|
-
end
|
186
|
-
|
187
|
-
refute_problems
|
188
|
-
end
|
189
|
-
|
190
|
-
def test_not_null_check_constraint
|
191
|
-
skip unless postgresql?
|
192
|
-
|
193
|
-
create_table(:users) do |t|
|
194
|
-
t.string :email
|
195
|
-
end.define_model do
|
196
|
-
validates :email, presence: true
|
197
|
-
end
|
198
|
-
|
199
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
200
|
-
ALTER TABLE users ADD CONSTRAINT email_not_null CHECK (email IS NOT NULL)
|
201
|
-
SQL
|
202
|
-
|
203
|
-
refute_problems
|
204
|
-
end
|
205
|
-
|
206
|
-
def test_not_null_check_constraint_not_valid
|
207
|
-
skip unless postgresql?
|
208
|
-
|
209
|
-
create_table(:users) do |t|
|
210
|
-
t.string :email
|
211
|
-
end.define_model do
|
212
|
-
validates :email, presence: true
|
213
|
-
end
|
214
|
-
|
215
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
216
|
-
ALTER TABLE users ADD CONSTRAINT email_not_null CHECK (email IS NOT NULL) NOT VALID
|
217
|
-
SQL
|
218
|
-
|
219
|
-
assert_problems(<<~OUTPUT)
|
220
|
-
add `NOT NULL` to users.email - models validates its presence but it's not non-NULL in the database
|
221
|
-
OUTPUT
|
222
|
-
end
|
223
|
-
|
224
|
-
def test_config_ignore_tables
|
225
|
-
create_table(:users) do |t|
|
226
|
-
t.string :name, null: true
|
227
|
-
end.define_model do
|
228
|
-
validates :name, presence: true
|
229
|
-
end
|
230
|
-
|
231
|
-
config_file(<<-CONFIG)
|
232
|
-
ActiveRecordDoctor.configure do |config|
|
233
|
-
config.detector :missing_non_null_constraint,
|
234
|
-
ignore_tables: ["users"]
|
235
|
-
end
|
236
|
-
CONFIG
|
237
|
-
|
238
|
-
refute_problems
|
239
|
-
end
|
240
|
-
|
241
|
-
def test_global_ignore_tables
|
242
|
-
create_table(:users) do |t|
|
243
|
-
t.string :name, null: true
|
244
|
-
end.define_model do
|
245
|
-
validates :name, presence: true
|
246
|
-
end
|
247
|
-
|
248
|
-
config_file(<<-CONFIG)
|
249
|
-
ActiveRecordDoctor.configure do |config|
|
250
|
-
config.global :ignore_tables, ["users"]
|
251
|
-
end
|
252
|
-
CONFIG
|
253
|
-
|
254
|
-
refute_problems
|
255
|
-
end
|
256
|
-
|
257
|
-
def test_config_ignore_columns
|
258
|
-
create_table(:users) do |t|
|
259
|
-
t.string :name, null: true
|
260
|
-
end.define_model do
|
261
|
-
validates :name, presence: true
|
262
|
-
end
|
263
|
-
|
264
|
-
config_file(<<-CONFIG)
|
265
|
-
ActiveRecordDoctor.configure do |config|
|
266
|
-
config.detector :missing_non_null_constraint,
|
267
|
-
ignore_columns: ["users.name"]
|
268
|
-
end
|
269
|
-
CONFIG
|
270
|
-
|
271
|
-
refute_problems
|
272
|
-
end
|
273
|
-
end
|
@@ -1,232 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::Detectors::MissingPresenceValidationTest < Minitest::Test
|
4
|
-
def test_null_column_is_not_reported_if_validation_absent
|
5
|
-
create_table(:users) do |t|
|
6
|
-
t.string :name
|
7
|
-
end.define_model do
|
8
|
-
end
|
9
|
-
|
10
|
-
refute_problems
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_non_null_column_is_reported_if_validation_absent
|
14
|
-
create_table(:users) do |t|
|
15
|
-
t.string :name, null: false
|
16
|
-
end.define_model do
|
17
|
-
end
|
18
|
-
|
19
|
-
assert_problems(<<~OUTPUT)
|
20
|
-
add a `presence` validator to TransientRecord::Models::User.name - it's NOT NULL but lacks a validator
|
21
|
-
OUTPUT
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_non_null_column_is_not_reported_if_validation_present
|
25
|
-
create_table(:users) do |t|
|
26
|
-
t.string :name, null: false
|
27
|
-
end.define_model do
|
28
|
-
validates :name, presence: true
|
29
|
-
end
|
30
|
-
|
31
|
-
refute_problems
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_non_null_column_is_not_reported_if_association_validation_present
|
35
|
-
create_table(:companies).define_model
|
36
|
-
create_table(:users) do |t|
|
37
|
-
t.references :company, null: false
|
38
|
-
end.define_model do
|
39
|
-
belongs_to :company, required: true
|
40
|
-
end
|
41
|
-
|
42
|
-
refute_problems
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_not_null_column_is_not_reported_if_habtm_association
|
46
|
-
create_table(:users).define_model do
|
47
|
-
has_and_belongs_to_many :projects, class_name: "TransientRecord::Models::Project"
|
48
|
-
end
|
49
|
-
|
50
|
-
create_table(:projects_users) do |t|
|
51
|
-
t.bigint :project_id, null: false
|
52
|
-
t.bigint :user_id, null: false
|
53
|
-
end
|
54
|
-
|
55
|
-
create_table(:projects).define_model do
|
56
|
-
has_and_belongs_to_many :users, class_name: "TransientRecord::Models::User"
|
57
|
-
end
|
58
|
-
|
59
|
-
refute_problems
|
60
|
-
end
|
61
|
-
|
62
|
-
def test_non_null_boolean_is_reported_if_nil_included
|
63
|
-
create_table(:users) do |t|
|
64
|
-
t.boolean :active, null: false
|
65
|
-
end.define_model do
|
66
|
-
validates :active, inclusion: { in: [nil, true, false] }
|
67
|
-
end
|
68
|
-
|
69
|
-
assert_problems(<<~OUTPUT)
|
70
|
-
add a `presence` validator to TransientRecord::Models::User.active - it's NOT NULL but lacks a validator
|
71
|
-
OUTPUT
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_non_null_boolean_is_not_reported_if_nil_not_included
|
75
|
-
create_table(:users) do |t|
|
76
|
-
t.boolean :active, null: false
|
77
|
-
end.define_model do
|
78
|
-
validates :active, inclusion: { in: [true, false] }
|
79
|
-
end
|
80
|
-
|
81
|
-
refute_problems
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_non_null_boolean_is_not_reported_if_nil_excluded
|
85
|
-
create_table(:users) do |t|
|
86
|
-
t.boolean :active, null: false
|
87
|
-
end.define_model do
|
88
|
-
validates :active, exclusion: { in: [nil] }
|
89
|
-
end
|
90
|
-
|
91
|
-
refute_problems
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_non_null_boolean_is_not_reported_if_exclusion_is_proc
|
95
|
-
create_table(:users) do |t|
|
96
|
-
t.boolean :active, null: false
|
97
|
-
end.define_model do
|
98
|
-
validates :active, exclusion: { in: ->(_user) { [nil] } }
|
99
|
-
end
|
100
|
-
|
101
|
-
refute_problems
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_non_null_boolean_is_not_reported_if_inclusion_is_proc
|
105
|
-
create_table(:users) do |t|
|
106
|
-
t.boolean :active, null: false
|
107
|
-
end.define_model do
|
108
|
-
validates :active, inclusion: { in: ->(_user) { [true, false] } }
|
109
|
-
end
|
110
|
-
|
111
|
-
refute_problems
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_non_null_boolean_is_reported_if_nil_not_excluded
|
115
|
-
create_table(:users) do |t|
|
116
|
-
t.boolean :active, null: false
|
117
|
-
end.define_model do
|
118
|
-
validates :active, exclusion: { in: [false] }
|
119
|
-
end
|
120
|
-
|
121
|
-
assert_problems(<<~OUTPUT)
|
122
|
-
add a `presence` validator to TransientRecord::Models::User.active - it's NOT NULL but lacks a validator
|
123
|
-
OUTPUT
|
124
|
-
end
|
125
|
-
|
126
|
-
def test_timestamps_are_not_reported
|
127
|
-
create_table(:users) do |t|
|
128
|
-
# Create created_at/updated_at timestamps.
|
129
|
-
t.timestamps null: false
|
130
|
-
|
131
|
-
# Rails also supports created_on/updated_on. We used datetime, which is
|
132
|
-
# what the timestamps method users under the hood, to avoid default value
|
133
|
-
# errors in some MySQL versions when using t.timestamp.
|
134
|
-
t.datetime :created_on, null: false
|
135
|
-
t.datetime :updated_on, null: false
|
136
|
-
end.define_model do
|
137
|
-
end
|
138
|
-
|
139
|
-
refute_problems
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_models_with_non_existent_tables_are_skipped
|
143
|
-
define_model(:User)
|
144
|
-
|
145
|
-
refute_problems
|
146
|
-
end
|
147
|
-
|
148
|
-
def test_not_null_check_constraint
|
149
|
-
skip unless postgresql?
|
150
|
-
|
151
|
-
create_table(:users) do |t|
|
152
|
-
t.string :name
|
153
|
-
end.define_model
|
154
|
-
|
155
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
156
|
-
ALTER TABLE users ADD CONSTRAINT name_not_null CHECK (name IS NOT NULL)
|
157
|
-
SQL
|
158
|
-
|
159
|
-
assert_problems(<<~OUTPUT)
|
160
|
-
add a `presence` validator to TransientRecord::Models::User.name - it's NOT NULL but lacks a validator
|
161
|
-
OUTPUT
|
162
|
-
end
|
163
|
-
|
164
|
-
def test_not_null_check_constraint_not_valid
|
165
|
-
skip unless postgresql?
|
166
|
-
|
167
|
-
create_table(:users) do |t|
|
168
|
-
t.string :name
|
169
|
-
end.define_model
|
170
|
-
|
171
|
-
ActiveRecord::Base.connection.execute(<<-SQL)
|
172
|
-
ALTER TABLE users ADD CONSTRAINT name_not_null CHECK (name IS NOT NULL) NOT VALID
|
173
|
-
SQL
|
174
|
-
|
175
|
-
refute_problems
|
176
|
-
end
|
177
|
-
|
178
|
-
def test_abstract_class
|
179
|
-
define_model(:ApplicationRecord) do
|
180
|
-
self.abstract_class = true
|
181
|
-
end
|
182
|
-
|
183
|
-
refute_problems
|
184
|
-
end
|
185
|
-
|
186
|
-
def test_config_ignore_models
|
187
|
-
create_table(:users) do |t|
|
188
|
-
t.string :name, null: false
|
189
|
-
end.define_model do
|
190
|
-
end
|
191
|
-
|
192
|
-
config_file(<<-CONFIG)
|
193
|
-
ActiveRecordDoctor.configure do |config|
|
194
|
-
config.detector :missing_presence_validation,
|
195
|
-
ignore_models: ["TransientRecord::Models::User"]
|
196
|
-
end
|
197
|
-
CONFIG
|
198
|
-
|
199
|
-
refute_problems
|
200
|
-
end
|
201
|
-
|
202
|
-
def test_global_ignore_models
|
203
|
-
create_table(:users) do |t|
|
204
|
-
t.string :name, null: false
|
205
|
-
end.define_model do
|
206
|
-
end
|
207
|
-
|
208
|
-
config_file(<<-CONFIG)
|
209
|
-
ActiveRecordDoctor.configure do |config|
|
210
|
-
config.global :ignore_models, ["TransientRecord::Models::User"]
|
211
|
-
end
|
212
|
-
CONFIG
|
213
|
-
|
214
|
-
refute_problems
|
215
|
-
end
|
216
|
-
|
217
|
-
def test_config_ignore_attributes
|
218
|
-
create_table(:users) do |t|
|
219
|
-
t.string :name, null: false
|
220
|
-
end.define_model do
|
221
|
-
end
|
222
|
-
|
223
|
-
config_file(<<-CONFIG)
|
224
|
-
ActiveRecordDoctor.configure do |config|
|
225
|
-
config.detector :missing_presence_validation,
|
226
|
-
ignore_attributes: ["TransientRecord::Models::User.name"]
|
227
|
-
end
|
228
|
-
CONFIG
|
229
|
-
|
230
|
-
refute_problems
|
231
|
-
end
|
232
|
-
end
|