active_record_doctor 1.8.0 → 1.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +246 -48
  3. data/lib/active_record_doctor/config/default.rb +59 -0
  4. data/lib/active_record_doctor/config/loader.rb +137 -0
  5. data/lib/active_record_doctor/config.rb +14 -0
  6. data/lib/active_record_doctor/detectors/base.rb +110 -19
  7. data/lib/active_record_doctor/detectors/extraneous_indexes.rb +63 -37
  8. data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +32 -23
  9. data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +70 -34
  10. data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +45 -0
  11. data/lib/active_record_doctor/detectors/missing_foreign_keys.rb +32 -23
  12. data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +40 -28
  13. data/lib/active_record_doctor/detectors/missing_presence_validation.rb +28 -21
  14. data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +40 -30
  15. data/lib/active_record_doctor/detectors/short_primary_key_type.rb +41 -0
  16. data/lib/active_record_doctor/detectors/undefined_table_references.rb +19 -20
  17. data/lib/active_record_doctor/detectors/unindexed_deleted_at.rb +44 -18
  18. data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +31 -20
  19. data/lib/active_record_doctor/detectors.rb +12 -4
  20. data/lib/active_record_doctor/errors.rb +226 -0
  21. data/lib/active_record_doctor/help.rb +39 -0
  22. data/lib/active_record_doctor/rake/task.rb +78 -0
  23. data/lib/active_record_doctor/runner.rb +41 -0
  24. data/lib/active_record_doctor/version.rb +1 -1
  25. data/lib/active_record_doctor.rb +7 -3
  26. data/lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb +34 -21
  27. data/lib/tasks/active_record_doctor.rake +9 -18
  28. data/test/active_record_doctor/config/loader_test.rb +120 -0
  29. data/test/active_record_doctor/config_test.rb +116 -0
  30. data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +131 -8
  31. data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +48 -5
  32. data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +190 -12
  33. data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +82 -0
  34. data/test/active_record_doctor/detectors/missing_foreign_keys_test.rb +50 -4
  35. data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +138 -24
  36. data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +74 -13
  37. data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +57 -8
  38. data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +64 -0
  39. data/test/active_record_doctor/detectors/undefined_table_references_test.rb +34 -21
  40. data/test/active_record_doctor/detectors/unindexed_deleted_at_test.rb +112 -8
  41. data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +56 -4
  42. data/test/active_record_doctor/runner_test.rb +42 -0
  43. data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +131 -0
  44. data/test/model_factory.rb +73 -23
  45. data/test/setup.rb +62 -72
  46. metadata +40 -9
  47. data/lib/active_record_doctor/printers/io_printer.rb +0 -133
  48. data/lib/active_record_doctor/task.rb +0 -28
  49. data/test/active_record_doctor/printers/io_printer_test.rb +0 -33
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveRecordDoctor::ConfigTest < Minitest::Test
4
+ def test_merge_globals_empty
5
+ config1 = ActiveRecordDoctor::Config.new({}, {})
6
+ config2 = ActiveRecordDoctor::Config.new({}, {})
7
+
8
+ config = config1.merge(config2)
9
+
10
+ assert_equal({}, config.globals)
11
+ end
12
+
13
+ def test_merge_globals_in_config1
14
+ config1 = ActiveRecordDoctor::Config.new(
15
+ { config1_global: "config1:config1_global" },
16
+ {}
17
+ )
18
+ config2 = ActiveRecordDoctor::Config.new({}, {})
19
+
20
+ config = config1.merge(config2)
21
+
22
+ assert_equal(
23
+ { config1_global: "config1:config1_global" },
24
+ config.globals
25
+ )
26
+ end
27
+
28
+ def test_merge_globals_in_config2
29
+ config1 = ActiveRecordDoctor::Config.new({}, {})
30
+ config2 = ActiveRecordDoctor::Config.new(
31
+ { config2_global: "config2:config2_global" },
32
+ {}
33
+ )
34
+
35
+ config = config1.merge(config2)
36
+
37
+ assert_equal(
38
+ { config2_global: "config2:config2_global" },
39
+ config.globals
40
+ )
41
+ end
42
+
43
+ def test_merge_globals_in_config1_and_config2
44
+ config1 = ActiveRecordDoctor::Config.new(
45
+ {
46
+ config1_global: "config1:config1_global",
47
+ shared_global: "config1:shared_global"
48
+ },
49
+ {}
50
+ )
51
+ config2 = ActiveRecordDoctor::Config.new(
52
+ {
53
+ config2_global: "config2:config2_global",
54
+ shared_global: "config2:shared_global"
55
+ },
56
+ {}
57
+ )
58
+
59
+ config = config1.merge(config2)
60
+
61
+ assert_equal(
62
+ {
63
+ config1_global: "config1:config1_global",
64
+ shared_global: "config2:shared_global",
65
+ config2_global: "config2:config2_global"
66
+ },
67
+ config.globals
68
+ )
69
+ end
70
+
71
+ def test_merge_detectors
72
+ config1 = ActiveRecordDoctor::Config.new(
73
+ {},
74
+ {
75
+ config1_detector: {
76
+ config1_setting: "config1:config1_detector.config1_setting"
77
+ },
78
+ shared_detector: {
79
+ config1_setting: "config1:shared_detector.config1_setting",
80
+ shared_setting: "config1:shared_detector.shared_setting"
81
+ }
82
+ }
83
+ )
84
+ config2 = ActiveRecordDoctor::Config.new(
85
+ {},
86
+ {
87
+ config2_detector: {
88
+ config2_setting: "config2:config2_detector.config2_setting"
89
+ },
90
+ shared_detector: {
91
+ config2_setting: "config2:shared_detector.config2_setting",
92
+ shared_setting: "config2:shared_detector.shared_setting"
93
+ }
94
+ }
95
+ )
96
+
97
+ config = config1.merge(config2)
98
+
99
+ assert_equal(
100
+ {
101
+ config1_detector: {
102
+ config1_setting: "config1:config1_detector.config1_setting"
103
+ },
104
+ config2_detector: {
105
+ config2_setting: "config2:config2_detector.config2_setting"
106
+ },
107
+ shared_detector: {
108
+ config1_setting: "config1:shared_detector.config1_setting",
109
+ config2_setting: "config2:shared_detector.config2_setting",
110
+ shared_setting: "config2:shared_detector.shared_setting"
111
+ }
112
+ },
113
+ config.detectors
114
+ )
115
+ end
116
+ end
@@ -7,8 +7,7 @@ class ActiveRecordDoctor::Detectors::ExtraneousIndexesTest < Minitest::Test
7
7
  end
8
8
 
9
9
  assert_problems(<<OUTPUT)
10
- The following indexes are extraneous and can be removed:
11
- index_users_on_id (is a primary key of users)
10
+ remove index_users_on_id - coincides with the primary key on the table
12
11
  OUTPUT
13
12
  end
14
13
 
@@ -22,8 +21,7 @@ OUTPUT
22
21
  ActiveRecord::Base.connection.add_index :users, :email, name: "index_users_on_email"
23
22
 
24
23
  assert_problems(<<OUTPUT)
25
- The following indexes are extraneous and can be removed:
26
- index_users_on_email (can be handled by unique_index_on_users_email)
24
+ remove index_users_on_email - can be replaced by unique_index_on_users_email
27
25
  OUTPUT
28
26
  end
29
27
 
@@ -40,8 +38,7 @@ OUTPUT
40
38
  end
41
39
 
42
40
  assert_problems(<<OUTPUT)
43
- The following indexes are extraneous and can be removed:
44
- index_users_on_last_name (can be handled by index_users_on_last_name_and_first_name_and_email, unique_index_on_users_last_name_and_first_name)
41
+ remove index_users_on_last_name - can be replaced by index_users_on_last_name_and_first_name_and_email or unique_index_on_users_last_name_and_first_name
45
42
  OUTPUT
46
43
  end
47
44
 
@@ -60,8 +57,134 @@ OUTPUT
60
57
  ActiveRecord::Base.connection.add_index :users, [:last_name, :first_name]
61
58
 
62
59
  assert_problems(<<OUTPUT)
63
- The following indexes are extraneous and can be removed:
64
- index_users_on_last_name_and_first_name (can be handled by index_users_on_last_name_and_first_name_and_email, unique_index_on_users_last_name_and_first_name)
60
+ remove index_users_on_last_name_and_first_name - can be replaced by index_users_on_last_name_and_first_name_and_email or unique_index_on_users_last_name_and_first_name
65
61
  OUTPUT
66
62
  end
63
+
64
+ def test_not_covered_by_different_index_type
65
+ create_table(:users) do |t|
66
+ t.string :first_name
67
+ t.string :last_name
68
+ t.index [:last_name, :first_name], using: :btree
69
+
70
+ if mysql?
71
+ t.index :last_name, type: :fulltext
72
+ else
73
+ t.index :last_name, using: :hash
74
+ end
75
+ end
76
+
77
+ refute_problems
78
+ end
79
+
80
+ def test_not_covered_by_partial_index
81
+ skip("MySQL doesn't support partial indexes") if mysql?
82
+
83
+ create_table(:users) do |t|
84
+ t.string :first_name
85
+ t.string :last_name
86
+ t.boolean :active
87
+ t.index [:last_name, :first_name], where: "active"
88
+ t.index :last_name
89
+ end
90
+
91
+ refute_problems
92
+ end
93
+
94
+ def test_not_covered_with_different_opclasses
95
+ skip("ActiveRecord < 5.2 doesn't support operator classes") if ActiveRecord::VERSION::STRING < "5.2"
96
+ skip("MySQL doesn't support operator classes") if mysql?
97
+
98
+ create_table(:users) do |t|
99
+ t.string :first_name
100
+ t.string :last_name
101
+ t.index [:last_name, :first_name], opclass: :varchar_pattern_ops
102
+ t.index :last_name
103
+ end
104
+
105
+ refute_problems
106
+ end
107
+
108
+ def test_config_ignore_tables
109
+ # The detector recognizes two kinds of errors and both must take
110
+ # ignore_tables into account. We trigger those errors by indexing the
111
+ # primary key (the first extraneous index) and then indexing email twice
112
+ # (index2... is the other extraneous index).
113
+ create_table(:users) do |t|
114
+ t.index :id
115
+ t.string :email
116
+
117
+ t.index :email, name: "index1_on_users_email"
118
+ t.index :email, name: "index2_on_users_email"
119
+ end
120
+
121
+ config_file(<<-CONFIG)
122
+ ActiveRecordDoctor.configure do |config|
123
+ config.detector :extraneous_indexes,
124
+ ignore_tables: ["users"]
125
+ end
126
+ CONFIG
127
+
128
+ refute_problems
129
+ end
130
+
131
+ def test_config_global_ignore_tables
132
+ create_table(:users) do |t|
133
+ t.index :id
134
+ t.string :email
135
+
136
+ t.index :email, name: "index1_on_users_email"
137
+ t.index :email, name: "index2_on_users_email"
138
+ end
139
+
140
+ config_file(<<-CONFIG)
141
+ ActiveRecordDoctor.configure do |config|
142
+ config.global :ignore_tables, ["users"]
143
+ end
144
+ CONFIG
145
+
146
+ refute_problems
147
+ end
148
+
149
+ def test_config_global_ignore_indexes
150
+ create_table(:users) do |t|
151
+ t.index :id
152
+ t.string :email
153
+
154
+ t.index :email, name: "index1_on_users_email"
155
+ t.index :email, name: "index2_on_users_email"
156
+ end
157
+
158
+ config_file(<<-CONFIG)
159
+ ActiveRecordDoctor.configure do |config|
160
+ config.global :ignore_indexes, [
161
+ "index1_on_users_email",
162
+ "index2_on_users_email",
163
+ "index_users_on_id",
164
+ ]
165
+ end
166
+ CONFIG
167
+
168
+ refute_problems
169
+ end
170
+
171
+ def test_config_detector_ignore_indexes
172
+ create_table(:users) do |t|
173
+ t.index :id
174
+ t.string :email
175
+ t.string :api_key
176
+
177
+ t.index :email, name: "index_on_users_email"
178
+ t.index [:email, :api_key], name: "index_on_users_email_and_api_key"
179
+ end
180
+
181
+ config_file(<<-CONFIG)
182
+ ActiveRecordDoctor.configure do |config|
183
+ config.detector :extraneous_indexes,
184
+ ignore_indexes: ["index_users_on_id", "index_on_users_email"]
185
+ end
186
+ CONFIG
187
+
188
+ refute_problems
189
+ end
67
190
  end
@@ -12,10 +12,9 @@ class ActiveRecordDoctor::Detectors::IncorrectBooleanPresenceValidationTest < Mi
12
12
  validates :email, :active, presence: true
13
13
  end
14
14
 
15
- assert_problems(<<OUTPUT)
16
- The presence of the following boolean columns is validated incorrectly:
17
- ModelFactory::Models::User: active
18
- OUTPUT
15
+ assert_problems(<<~OUTPUT)
16
+ replace the `presence` validator on ModelFactory::Models::User.active with `inclusion` - `presence` can't be used on booleans
17
+ OUTPUT
19
18
  end
20
19
 
21
20
  def test_inclusion_is_not_reported
@@ -29,7 +28,51 @@ OUTPUT
29
28
  end
30
29
 
31
30
  def test_models_with_non_existent_tables_are_skipped
32
- create_model(:users)
31
+ create_model(:User)
32
+
33
+ refute_problems
34
+ end
35
+
36
+ def test_config_ignore_models
37
+ create_table(:users) do |t|
38
+ t.string :email, null: false
39
+ end.create_model
40
+
41
+ config_file(<<-CONFIG)
42
+ ActiveRecordDoctor.configure do |config|
43
+ config.detector :incorrect_boolean_presence_validation,
44
+ ignore_models: ["ModelFactory.User"]
45
+ end
46
+ CONFIG
47
+
48
+ refute_problems
49
+ end
50
+
51
+ def test_global_ignore_models
52
+ create_table(:users) do |t|
53
+ t.string :email, null: false
54
+ end.create_model
55
+
56
+ config_file(<<-CONFIG)
57
+ ActiveRecordDoctor.configure do |config|
58
+ config.global :ignore_models, ["ModelFactory.User"]
59
+ end
60
+ CONFIG
61
+
62
+ refute_problems
63
+ end
64
+
65
+ def test_config_ignore_attributes
66
+ create_table(:users) do |t|
67
+ t.string :email, null: false
68
+ end.create_model
69
+
70
+ config_file(<<-CONFIG)
71
+ ActiveRecordDoctor.configure do |config|
72
+ config.detector :incorrect_boolean_presence_validation,
73
+ ignore_attributes: ["ModelFactory.User.email"]
74
+ end
75
+ CONFIG
33
76
 
34
77
  refute_problems
35
78
  end
@@ -13,10 +13,9 @@ class ActiveRecordDoctor::Detectors::IncorrectDependentOptionTest < Minitest::Te
13
13
  belongs_to :company
14
14
  end
15
15
 
16
- assert_problems(<<OUTPUT)
17
- The following associations might be using invalid dependent settings:
18
- ModelFactory::Models::Company: users loads models one-by-one to invoke callbacks even though the related model defines none - consider using `dependent: :delete_all`
19
- OUTPUT
16
+ assert_problems(<<~OUTPUT)
17
+ use `dependent: :delete_all` or similar on ModelFactory::Models::Company.users - associated models have no validations and can be deleted in bulk
18
+ OUTPUT
20
19
  end
21
20
 
22
21
  def test_invoking_callbacks_does_not_suggest_delete_all
@@ -56,10 +55,9 @@ OUTPUT
56
55
  end
57
56
  end
58
57
 
59
- assert_problems(<<OUTPUT)
60
- The following associations might be using invalid dependent settings:
61
- ModelFactory::Models::Company: users skips callbacks that are defined on the associated model - consider changing to `dependent: :destroy` or similar
62
- OUTPUT
58
+ assert_problems(<<~OUTPUT)
59
+ use `dependent: :destroy` or similar on ModelFactory::Models::Company.users - the associated model has callbacks that are currently skipped
60
+ OUTPUT
63
61
  end
64
62
 
65
63
  def test_invoking_callbacks_does_not_suggest_destroy
@@ -94,10 +92,125 @@ OUTPUT
94
92
  belongs_to :company
95
93
  end
96
94
 
97
- assert_problems(<<OUTPUT)
98
- The following associations might be using invalid dependent settings:
99
- ModelFactory::Models::Company: owner loads the associated model before deleting it - consider using `dependent: :delete`
100
- OUTPUT
95
+ assert_problems(<<~OUTPUT)
96
+ use `dependent: :delete` or similar on ModelFactory::Models::Company.owner - the associated model has no callbacks and can be deleted without loading
97
+ OUTPUT
98
+ end
99
+
100
+ def test_works_on_belongs_to
101
+ create_table(:companies) do
102
+ end.create_model do
103
+ has_many :users
104
+ end
105
+
106
+ create_table(:users) do |t|
107
+ t.references :company
108
+ end.create_model do
109
+ belongs_to :company, dependent: :destroy
110
+ end
111
+
112
+ assert_problems(<<~OUTPUT)
113
+ use `dependent: :delete` or similar on ModelFactory::Models::User.company - the associated model has no callbacks and can be deleted without loading
114
+ OUTPUT
115
+ end
116
+
117
+ def test_no_foreign_key_on_second_level_association
118
+ create_table(:companies) do
119
+ end.create_model do
120
+ has_many :users
121
+ has_many :projects
122
+ end
123
+
124
+ create_table(:users) do |t|
125
+ t.references :company
126
+ end.create_model do
127
+ belongs_to :company, dependent: :destroy
128
+ end
129
+
130
+ create_table(:projects) do |t|
131
+ t.references :company
132
+ end.create_model do
133
+ belongs_to :company
134
+ end
135
+
136
+ assert_problems(<<~OUTPUT)
137
+ use `dependent: :delete` or similar on ModelFactory::Models::User.company - the associated model has no callbacks and can be deleted without loading
138
+ OUTPUT
139
+ end
140
+
141
+ def test_nullify_foreign_key_on_second_level_association
142
+ create_table(:companies) do
143
+ end.create_model do
144
+ has_many :users
145
+ has_many :projects
146
+ end
147
+
148
+ create_table(:users) do |t|
149
+ t.references :company
150
+ end.create_model do
151
+ belongs_to :company, dependent: :destroy
152
+ end
153
+
154
+ create_table(:projects) do |t|
155
+ t.references :company, foreign_key: { on_delete: :nullify }
156
+ end.create_model do
157
+ belongs_to :company
158
+ end
159
+
160
+ assert_problems(<<~OUTPUT)
161
+ use `dependent: :delete` or similar on ModelFactory::Models::User.company - the associated model has no callbacks and can be deleted without loading
162
+ OUTPUT
163
+ end
164
+
165
+ def test_cascade_foreign_key_and_callbacks_on_second_level_association
166
+ create_table(:companies) do
167
+ end.create_model do
168
+ has_many :users
169
+ has_many :projects
170
+ end
171
+
172
+ create_table(:users) do |t|
173
+ t.references :company
174
+ end.create_model do
175
+ belongs_to :company, dependent: :delete
176
+ end
177
+
178
+ create_table(:projects) do |t|
179
+ t.references :company, foreign_key: { on_delete: :cascade }
180
+ end.create_model do
181
+ belongs_to :company
182
+
183
+ before_destroy :log
184
+
185
+ def log
186
+ end
187
+ end
188
+
189
+ assert_problems(<<~OUTPUT)
190
+ use `dependent: :destroy` or similar on ModelFactory::Models::User.company - the associated model has callbacks that are currently skipped
191
+ OUTPUT
192
+ end
193
+
194
+ def test_cascade_foreign_key_and_no_callbacks_on_second_level_association
195
+ create_table(:companies) do
196
+ end.create_model do
197
+ has_many :users
198
+ has_many :projects
199
+ end
200
+
201
+ create_table(:users) do |t|
202
+ t.references :company
203
+ end.create_model do
204
+ belongs_to :company, dependent: :delete
205
+ end
206
+
207
+ create_table(:projects) do |t|
208
+ t.references :company, foreign_key: { on_delete: :cascade }
209
+ end.create_model do
210
+ belongs_to :company
211
+ end
212
+
213
+ refute_problems
101
214
  end
102
215
 
103
216
  def test_no_dependent_suggests_nothing
@@ -114,4 +227,69 @@ OUTPUT
114
227
 
115
228
  refute_problems
116
229
  end
230
+
231
+ def test_config_ignore_models
232
+ create_table(:companies) do
233
+ end.create_model do
234
+ has_many :users, dependent: :destroy
235
+ end
236
+
237
+ create_table(:users) do |t|
238
+ t.references :companies
239
+ end.create_model do
240
+ belongs_to :company
241
+ end
242
+
243
+ config_file(<<-CONFIG)
244
+ ActiveRecordDoctor.configure do |config|
245
+ config.detector :incorrect_dependent_option,
246
+ ignore_models: ["ModelFactory::Models::Company"]
247
+ end
248
+ CONFIG
249
+
250
+ refute_problems
251
+ end
252
+
253
+ def test_global_ignore_models
254
+ create_table(:companies) do
255
+ end.create_model do
256
+ has_many :users, dependent: :destroy
257
+ end
258
+
259
+ create_table(:users) do |t|
260
+ t.references :companies
261
+ end.create_model do
262
+ belongs_to :company
263
+ end
264
+
265
+ config_file(<<-CONFIG)
266
+ ActiveRecordDoctor.configure do |config|
267
+ config.global :ignore_models, ["ModelFactory::Models::Company"]
268
+ end
269
+ CONFIG
270
+
271
+ refute_problems
272
+ end
273
+
274
+ def test_config_ignore_associations
275
+ create_table(:companies) do
276
+ end.create_model do
277
+ has_many :users, dependent: :destroy
278
+ end
279
+
280
+ create_table(:users) do |t|
281
+ t.references :companies
282
+ end.create_model do
283
+ belongs_to :company
284
+ end
285
+
286
+ config_file(<<-CONFIG)
287
+ ActiveRecordDoctor.configure do |config|
288
+ config.detector :incorrect_dependent_option,
289
+ ignore_associations: ["ModelFactory::Models::Company.users"]
290
+ end
291
+ CONFIG
292
+
293
+ refute_problems
294
+ end
117
295
  end
@@ -0,0 +1,82 @@
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 references a column of different type - 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_config_ignore_tables
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)
32
+ create_table(:users) do |t|
33
+ t.references :company, foreign_key: true, type: :integer
34
+ end
35
+
36
+ config_file(<<-CONFIG)
37
+ ActiveRecordDoctor.configure do |config|
38
+ config.detector :mismatched_foreign_key_type,
39
+ ignore_tables: ["users"]
40
+ end
41
+ CONFIG
42
+
43
+ refute_problems
44
+ end
45
+
46
+ def test_global_ignore_tables
47
+ # MySQL does not allow foreign keys to have different type than paired primary keys
48
+ return if mysql?
49
+
50
+ create_table(:companies, id: :bigint)
51
+ create_table(:users) do |t|
52
+ t.references :company, foreign_key: true, type: :integer
53
+ end
54
+
55
+ config_file(<<-CONFIG)
56
+ ActiveRecordDoctor.configure do |config|
57
+ config.global :ignore_tables, ["users"]
58
+ end
59
+ CONFIG
60
+
61
+ refute_problems
62
+ end
63
+
64
+ def test_config_ignore_columns
65
+ # MySQL does not allow foreign keys to have different type than paired primary keys
66
+ return if mysql?
67
+
68
+ create_table(:companies, id: :bigint)
69
+ create_table(:users) do |t|
70
+ t.references :company, foreign_key: true, type: :integer
71
+ end
72
+
73
+ config_file(<<-CONFIG)
74
+ ActiveRecordDoctor.configure do |config|
75
+ config.detector :mismatched_foreign_key_type,
76
+ ignore_columns: ["users.company_id"]
77
+ end
78
+ CONFIG
79
+
80
+ refute_problems
81
+ end
82
+ end