active_record_doctor 1.12.0 → 1.14.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 +29 -2
- 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/rake/task.rb +35 -3
- 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 +1 -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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89e283c2844a768587302646735a080d8db2b3514775083cc6bc74a25e7aff18
|
4
|
+
data.tar.gz: 975a75da213c565dba3ee7918ffe64d5b75d812059b8080d6a5134a2fb27028f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca4a89d161ef3a57ee325ea6551417b9e542967d2f932f383eca6e7394ba99f02cf08ac9cd699e98f1f59018669405220fe1175f80d31f60576fc606d2d3f5f6
|
7
|
+
data.tar.gz: 70644778b22b9fe2892d12704cdfb3d81337702e8770ca94f8410694e3a8b12ad931bc511bc5188f77726849fca7c87c1ce8fec059d647ea4225adf6ab1363ef
|
data/README.md
CHANGED
@@ -55,7 +55,7 @@ ActiveRecordDoctor::Rake::Task.new do |task|
|
|
55
55
|
task.deps = []
|
56
56
|
|
57
57
|
# A path to your active_record_doctor configuration file.
|
58
|
-
task.config_path = ::Rails.root.join(".active_record_doctor")
|
58
|
+
task.config_path = ::Rails.root.join(".active_record_doctor.rb")
|
59
59
|
|
60
60
|
# A Proc called right before running detectors that should ensure your Active
|
61
61
|
# Record models are preloaded and a database connection is ready.
|
@@ -111,7 +111,7 @@ If you want to use the default configuration then you don't have to do anything.
|
|
111
111
|
Just run `active_record_doctor` in your project directory.
|
112
112
|
|
113
113
|
If you want to customize the tool you should create a file named
|
114
|
-
`.active_record_doctor` in your project root directory with content like:
|
114
|
+
`.active_record_doctor.rb` in your project root directory with content like:
|
115
115
|
|
116
116
|
```ruby
|
117
117
|
ActiveRecordDoctor.configure do
|
@@ -144,6 +144,33 @@ as extraneous.
|
|
144
144
|
Configuration options for each detector are listed below. They can also be
|
145
145
|
obtained via the help mechanism described in the previous section.
|
146
146
|
|
147
|
+
### Regexp-Based Ignores
|
148
|
+
|
149
|
+
Settings like `ignore_tables`, `ignore_indexes`, and so on accept list of
|
150
|
+
identifiers to ignore. These can be either:
|
151
|
+
|
152
|
+
1. Strings - in which case an exact match is needed.
|
153
|
+
2. Regexps - which are matched against object names, and matching ones are
|
154
|
+
excluded from output.
|
155
|
+
|
156
|
+
For example, to ignore all tables starting with `legacy_` you can write:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
ActiveRecordDoctor.configure do
|
160
|
+
global :ignore_tables, [
|
161
|
+
# Ignore internal Rails-related tables.
|
162
|
+
"ar_internal_metadata",
|
163
|
+
"schema_migrations",
|
164
|
+
"active_storage_blobs",
|
165
|
+
"active_storage_attachments",
|
166
|
+
"action_text_rich_texts",
|
167
|
+
|
168
|
+
# Ignore all legacy tables.
|
169
|
+
/^legacy_/
|
170
|
+
]
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
147
174
|
### Indexing Unindexed Foreign Keys
|
148
175
|
|
149
176
|
Foreign keys should be indexed unless it's proven ineffective. However, Rails
|
@@ -27,7 +27,7 @@ module ActiveRecordDoctor # :nodoc:
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# The same global can be used by multiple detectors so we must remove
|
30
|
-
# duplicates to ensure they aren't reported
|
30
|
+
# duplicates to ensure they aren't reported multiple times via the user
|
31
31
|
# interface (e.g. in error messages).
|
32
32
|
recognized_globals.uniq!
|
33
33
|
|
@@ -170,7 +170,7 @@ module ActiveRecordDoctor
|
|
170
170
|
case
|
171
171
|
when model.name.start_with?("HABTM_")
|
172
172
|
log("#{model.name} - has-belongs-to-many model; skipping")
|
173
|
-
when
|
173
|
+
when ignored?(model.name, except)
|
174
174
|
log("#{model.name} - ignored via the configuration; skipping")
|
175
175
|
when abstract && !model.abstract_class?
|
176
176
|
log("#{model.name} - non-abstract model; skipping")
|
@@ -200,7 +200,7 @@ module ActiveRecordDoctor
|
|
200
200
|
log(message) do
|
201
201
|
indexes.each do |index|
|
202
202
|
case
|
203
|
-
when
|
203
|
+
when ignored?(index.name, except)
|
204
204
|
log("#{index.name} - ignored via the configuration; skipping")
|
205
205
|
when multicolumn_only && !index.columns.is_a?(Array)
|
206
206
|
log("#{index.name} - single-column index; skipping")
|
@@ -217,7 +217,7 @@ module ActiveRecordDoctor
|
|
217
217
|
log("Iterating over attributes of #{model.name}") do
|
218
218
|
connection.columns(model.table_name).each do |column|
|
219
219
|
case
|
220
|
-
when
|
220
|
+
when ignored?("#{model.name}.#{column.name}", except)
|
221
221
|
log("#{model.name}.#{column.name} - ignored via the configuration; skipping")
|
222
222
|
when type && !Array(type).include?(column.type)
|
223
223
|
log("#{model.name}.#{column.name} - ignored due to the #{column.type} type; skipping")
|
@@ -234,7 +234,7 @@ module ActiveRecordDoctor
|
|
234
234
|
log("Iterating over columns of #{table_name}") do
|
235
235
|
connection.columns(table_name).each do |column|
|
236
236
|
case
|
237
|
-
when
|
237
|
+
when ignored?("#{table_name}.#{column.name}", except)
|
238
238
|
log("#{column.name} - ignored via the configuration; skipping")
|
239
239
|
when only.nil? || only.include?(column.name)
|
240
240
|
log(column.name.to_s) do
|
@@ -266,7 +266,7 @@ module ActiveRecordDoctor
|
|
266
266
|
log("Iterating over tables") do
|
267
267
|
tables.each do |table|
|
268
268
|
case
|
269
|
-
when
|
269
|
+
when ignored?(table, except)
|
270
270
|
log("#{table} - ignored via the configuration; skipping")
|
271
271
|
else
|
272
272
|
log(table) do
|
@@ -280,7 +280,7 @@ module ActiveRecordDoctor
|
|
280
280
|
def each_data_source(except: [])
|
281
281
|
log("Iterating over data sources") do
|
282
282
|
connection.data_sources.each do |data_source|
|
283
|
-
if
|
283
|
+
if ignored?(data_source, except)
|
284
284
|
log("#{data_source} - ignored via the configuration; skipping")
|
285
285
|
else
|
286
286
|
log(data_source) do
|
@@ -303,7 +303,7 @@ module ActiveRecordDoctor
|
|
303
303
|
|
304
304
|
associations.each do |association|
|
305
305
|
case
|
306
|
-
when
|
306
|
+
when ignored?("#{model.name}.#{association.name}", except)
|
307
307
|
log("#{model.name}.#{association.name} - ignored via the configuration; skipping")
|
308
308
|
when through && !association.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
309
309
|
log("#{model.name}.#{association.name} - is not a through association; skipping")
|
@@ -321,6 +321,10 @@ module ActiveRecordDoctor
|
|
321
321
|
end
|
322
322
|
end
|
323
323
|
end
|
324
|
+
|
325
|
+
def ignored?(name, patterns)
|
326
|
+
patterns.any? { |pattern| pattern === name } # rubocop:disable Style/CaseEquality
|
327
|
+
end
|
324
328
|
end
|
325
329
|
end
|
326
330
|
end
|
@@ -5,7 +5,7 @@ require "active_record_doctor/detectors/base"
|
|
5
5
|
module ActiveRecordDoctor
|
6
6
|
module Detectors
|
7
7
|
class IncorrectBooleanPresenceValidation < Base # :nodoc:
|
8
|
-
@description = "detect
|
8
|
+
@description = "detect presence (instead of inclusion) validators on boolean columns"
|
9
9
|
@config = {
|
10
10
|
ignore_models: {
|
11
11
|
description: "models whose validators should not be checked",
|
@@ -38,8 +38,8 @@ module ActiveRecordDoctor
|
|
38
38
|
when :invalid_through
|
39
39
|
"ensure #{model}.#{association} is configured correctly - #{associated_models[0]}.#{association} may be undefined"
|
40
40
|
when :destroy_async
|
41
|
-
"don't use `dependent: :destroy_async` on #{model}.#{association} or remove the foreign key from #{table_name}.#{column_name} - "\
|
42
|
-
|
41
|
+
"don't use `dependent: :destroy_async` on #{model}.#{association} or remove the foreign key from #{table_name}.#{column_name} - " \
|
42
|
+
"associated models will be deleted in the same transaction along with #{model}"
|
43
43
|
when :suggest_destroy
|
44
44
|
"use `dependent: :destroy` or similar on #{model}.#{association} - associated #{models_part} callbacks that are currently skipped"
|
45
45
|
when :suggest_delete
|
@@ -96,8 +96,13 @@ module ActiveRecordDoctor
|
|
96
96
|
when :destroy_async
|
97
97
|
foreign_key = foreign_key(association.klass.table_name, model.table_name)
|
98
98
|
if foreign_key
|
99
|
-
problem!(
|
100
|
-
|
99
|
+
problem!(
|
100
|
+
model: model.name,
|
101
|
+
association: association.name,
|
102
|
+
table_name: foreign_key.from_table,
|
103
|
+
column_name: foreign_key.column,
|
104
|
+
problem: :destroy_async
|
105
|
+
)
|
101
106
|
end
|
102
107
|
when :destroy
|
103
108
|
if destroyable_models.empty? && deletable_models.present?
|
@@ -29,7 +29,7 @@ module ActiveRecordDoctor
|
|
29
29
|
each_foreign_key(table) do |foreign_key|
|
30
30
|
from_column = column(table, foreign_key.column)
|
31
31
|
|
32
|
-
next if
|
32
|
+
next if ignored?("#{table}.#{from_column.name}", config(:ignore_columns))
|
33
33
|
|
34
34
|
to_table = foreign_key.to_table
|
35
35
|
to_column = column(to_table, foreign_key.primary_key)
|
@@ -26,14 +26,14 @@ module ActiveRecordDoctor
|
|
26
26
|
table_models = models.select(&:table_exists?).group_by(&:table_name)
|
27
27
|
|
28
28
|
table_models.each do |table, models|
|
29
|
-
next if config(:ignore_tables)
|
29
|
+
next if ignored?(table, config(:ignore_tables))
|
30
30
|
|
31
31
|
concrete_models = models.reject do |model|
|
32
32
|
model.abstract_class? || sti_base_model?(model)
|
33
33
|
end
|
34
34
|
|
35
35
|
connection.columns(table).each do |column|
|
36
|
-
next if
|
36
|
+
next if ignored?("#{table}.#{column.name}", config(:ignore_columns))
|
37
37
|
next if !column.null
|
38
38
|
next if !concrete_models.all? { |model| non_null_needed?(model, column) }
|
39
39
|
next if not_null_check_constraint_exists?(table, column)
|
@@ -24,8 +24,8 @@ module ActiveRecordDoctor
|
|
24
24
|
when :validations
|
25
25
|
"add a unique index on #{table}(#{columns.join(', ')}) - validating uniqueness in #{model.name} without an index can lead to duplicates"
|
26
26
|
when :case_insensitive_validations
|
27
|
-
"add a unique expression index on #{table}(#{columns.join(', ')}) - validating case-insensitive uniqueness in #{model.name} "\
|
28
|
-
|
27
|
+
"add a unique expression index on #{table}(#{columns.join(', ')}) - validating case-insensitive uniqueness in #{model.name} " \
|
28
|
+
"without an expression index can lead to duplicates (a regular unique index is not enough)"
|
29
29
|
when :has_ones
|
30
30
|
"add a unique index on #{table}(#{columns.join(', ')}) - using `has_one` in #{model.name} without an index can lead to duplicates"
|
31
31
|
end
|
@@ -70,8 +70,12 @@ module ActiveRecordDoctor
|
|
70
70
|
if case_sensitive
|
71
71
|
problem!(model: model, table: model.table_name, columns: columns, problem: :validations)
|
72
72
|
else
|
73
|
-
problem!(
|
74
|
-
|
73
|
+
problem!(
|
74
|
+
model: model,
|
75
|
+
table: model.table_name,
|
76
|
+
columns: columns,
|
77
|
+
problem: :case_insensitive_validations
|
78
|
+
)
|
75
79
|
end
|
76
80
|
end
|
77
81
|
end
|
@@ -81,7 +85,7 @@ module ActiveRecordDoctor
|
|
81
85
|
def has_ones_without_indexes # rubocop:disable Naming/PredicateName
|
82
86
|
each_model do |model|
|
83
87
|
each_association(model, type: :has_one, has_scope: false, through: false) do |has_one|
|
84
|
-
next if
|
88
|
+
next if ignored?(has_one.klass.name, config(:ignore_models))
|
85
89
|
|
86
90
|
columns =
|
87
91
|
if has_one.options[:as]
|
@@ -89,10 +93,11 @@ module ActiveRecordDoctor
|
|
89
93
|
else
|
90
94
|
[has_one.foreign_key.to_s]
|
91
95
|
end
|
92
|
-
next if
|
96
|
+
next if ignored?("#{has_one.klass.name}(#{columns.join(',')})", ignore_columns)
|
93
97
|
|
94
98
|
table_name = has_one.klass.table_name
|
95
99
|
next if unique_index?(table_name, columns)
|
100
|
+
next if Array(connection.primary_key(table_name)) == columns
|
96
101
|
|
97
102
|
problem!(model: model, table: table_name, columns: columns, problem: :has_ones)
|
98
103
|
end
|
@@ -136,7 +141,11 @@ module ActiveRecordDoctor
|
|
136
141
|
|
137
142
|
def ignore_columns
|
138
143
|
@ignore_columns ||= config(:ignore_columns).map do |column|
|
139
|
-
column.
|
144
|
+
if column.is_a?(String)
|
145
|
+
column.gsub(" ", "")
|
146
|
+
else
|
147
|
+
column
|
148
|
+
end
|
140
149
|
end
|
141
150
|
end
|
142
151
|
|
@@ -30,6 +30,7 @@ module ActiveRecordDoctor
|
|
30
30
|
next unless named_like_foreign_key?(column) || foreign_key?(table, column)
|
31
31
|
next if indexed?(table, column)
|
32
32
|
next if indexed_as_polymorphic?(table, column)
|
33
|
+
next if connection.primary_key(table) == column.name
|
33
34
|
|
34
35
|
type_column_name = type_column_name(column)
|
35
36
|
|
@@ -68,9 +68,41 @@ module ActiveRecordDoctor
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def config
|
71
|
-
@config ||=
|
72
|
-
|
73
|
-
|
71
|
+
@config ||=
|
72
|
+
ActiveRecordDoctor.load_config_with_defaults(effective_config_path)
|
73
|
+
end
|
74
|
+
|
75
|
+
def effective_config_path
|
76
|
+
if config_path.nil?
|
77
|
+
# No explicit config_path was set, so we're trying to use defaults.
|
78
|
+
legacy_default_path = Rails.root.join(".active_record_doctor")
|
79
|
+
new_default_path = Rails.root.join(".active_record_doctor.rb")
|
80
|
+
|
81
|
+
# First, if the legacy file exists we'll use it but show a warning.
|
82
|
+
if legacy_default_path.exist?
|
83
|
+
warn(<<~WARN.squish)
|
84
|
+
DEPRECATION WARNING: active_record_doctor is using the default
|
85
|
+
configuration file located in #{legacy_default_path.basename}. However,
|
86
|
+
that default will change to #{new_default_path.basename} in the future.
|
87
|
+
|
88
|
+
In order to avoid errors, please rename the file from
|
89
|
+
#{legacy_default_path.basename} to #{new_default_path.basename}.
|
90
|
+
WARN
|
91
|
+
|
92
|
+
return legacy_default_path
|
93
|
+
end
|
94
|
+
|
95
|
+
# Second, if the legacy file does NOT exist, but the new one does then
|
96
|
+
# we'll use that.
|
97
|
+
if new_default_path.exist?
|
98
|
+
return new_default_path
|
99
|
+
end
|
100
|
+
|
101
|
+
# Otherwise, there's no configuration file in use.
|
102
|
+
nil
|
103
|
+
else
|
104
|
+
# If an explicit configuration file was set then we use it as is.
|
105
|
+
config_path
|
74
106
|
end
|
75
107
|
end
|
76
108
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecordDoctor # :nodoc:
|
4
|
-
# An
|
4
|
+
# An execution environment for active_record_doctor that provides a config
|
5
5
|
# and an output device for use by detectors.
|
6
6
|
class Runner
|
7
7
|
# io is injected via constructor parameters to facilitate testing.
|
@@ -13,8 +13,8 @@ module ActiveRecordDoctor
|
|
13
13
|
|
14
14
|
def expression_indexes_unsupported?(connection = ActiveRecord::Base.connection)
|
15
15
|
(ActiveRecord::VERSION::STRING < "5.0") ||
|
16
|
-
# Active Record
|
17
|
-
(mysql?(connection) && ActiveRecord::VERSION::STRING < "
|
16
|
+
# Active Record is unable to correctly parse expression indexes for MySQL.
|
17
|
+
(mysql?(connection) && ActiveRecord::VERSION::STRING < "7.1")
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -19,6 +19,5 @@ ActiveRecordDoctor::Rake::Task.new do |task|
|
|
19
19
|
# This file is imported when active_record_doctor is being used as part of a
|
20
20
|
# Rails app so it's the right place for all Rails-specific settings.
|
21
21
|
task.deps = [:environment]
|
22
|
-
task.
|
23
|
-
task.setup = -> { ::Rails.application.eager_load! }
|
22
|
+
task.setup = -> { Rails.application.eager_load! }
|
24
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_doctor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Navis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.
|
61
|
+
version: 1.1.4
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.
|
68
|
+
version: 1.1.4
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: railties
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,28 +100,28 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - '='
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 2.0.0.rc2
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 2.0.0.rc2
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rubocop
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: 1.57.1
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.
|
124
|
+
version: 1.57.1
|
125
125
|
description:
|
126
126
|
email:
|
127
127
|
- contact@gregnavis.com
|
@@ -164,29 +164,11 @@ files:
|
|
164
164
|
- lib/generators/active_record_doctor/add_indexes/USAGE
|
165
165
|
- lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb
|
166
166
|
- lib/tasks/active_record_doctor.rake
|
167
|
-
- test/active_record_doctor/config/loader_test.rb
|
168
|
-
- test/active_record_doctor/config_test.rb
|
169
|
-
- test/active_record_doctor/detectors/disable_test.rb
|
170
|
-
- test/active_record_doctor/detectors/extraneous_indexes_test.rb
|
171
|
-
- test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb
|
172
|
-
- test/active_record_doctor/detectors/incorrect_dependent_option_test.rb
|
173
|
-
- test/active_record_doctor/detectors/incorrect_length_validation_test.rb
|
174
|
-
- test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb
|
175
|
-
- test/active_record_doctor/detectors/missing_foreign_keys_test.rb
|
176
|
-
- test/active_record_doctor/detectors/missing_non_null_constraint_test.rb
|
177
|
-
- test/active_record_doctor/detectors/missing_presence_validation_test.rb
|
178
|
-
- test/active_record_doctor/detectors/missing_unique_indexes_test.rb
|
179
|
-
- test/active_record_doctor/detectors/short_primary_key_type_test.rb
|
180
|
-
- test/active_record_doctor/detectors/undefined_table_references_test.rb
|
181
|
-
- test/active_record_doctor/detectors/unindexed_deleted_at_test.rb
|
182
|
-
- test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb
|
183
|
-
- test/active_record_doctor/runner_test.rb
|
184
|
-
- test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb
|
185
|
-
- test/setup.rb
|
186
167
|
homepage: https://github.com/gregnavis/active_record_doctor
|
187
168
|
licenses:
|
188
169
|
- MIT
|
189
|
-
metadata:
|
170
|
+
metadata:
|
171
|
+
rubygems_mfa_required: 'true'
|
190
172
|
post_install_message:
|
191
173
|
rdoc_options: []
|
192
174
|
require_paths:
|
@@ -202,27 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
202
184
|
- !ruby/object:Gem::Version
|
203
185
|
version: '0'
|
204
186
|
requirements: []
|
205
|
-
rubygems_version: 3.
|
187
|
+
rubygems_version: 3.3.26
|
206
188
|
signing_key:
|
207
189
|
specification_version: 4
|
208
190
|
summary: Identify database issues before they hit production.
|
209
|
-
test_files:
|
210
|
-
- test/active_record_doctor/config/loader_test.rb
|
211
|
-
- test/active_record_doctor/config_test.rb
|
212
|
-
- test/active_record_doctor/detectors/disable_test.rb
|
213
|
-
- test/active_record_doctor/detectors/extraneous_indexes_test.rb
|
214
|
-
- test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb
|
215
|
-
- test/active_record_doctor/detectors/incorrect_dependent_option_test.rb
|
216
|
-
- test/active_record_doctor/detectors/incorrect_length_validation_test.rb
|
217
|
-
- test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb
|
218
|
-
- test/active_record_doctor/detectors/missing_foreign_keys_test.rb
|
219
|
-
- test/active_record_doctor/detectors/missing_non_null_constraint_test.rb
|
220
|
-
- test/active_record_doctor/detectors/missing_presence_validation_test.rb
|
221
|
-
- test/active_record_doctor/detectors/missing_unique_indexes_test.rb
|
222
|
-
- test/active_record_doctor/detectors/short_primary_key_type_test.rb
|
223
|
-
- test/active_record_doctor/detectors/undefined_table_references_test.rb
|
224
|
-
- test/active_record_doctor/detectors/unindexed_deleted_at_test.rb
|
225
|
-
- test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb
|
226
|
-
- test/active_record_doctor/runner_test.rb
|
227
|
-
- test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb
|
228
|
-
- test/setup.rb
|
191
|
+
test_files: []
|
@@ -1,120 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class ActiveRecordDoctor::LoaderTest < Minitest::Test
|
4
|
-
def test_load_config
|
5
|
-
config_path = config_file(<<-CONFIG)
|
6
|
-
ActiveRecordDoctor.configure do |config|
|
7
|
-
config.global :ignore_tables, ["schema_migrations"]
|
8
|
-
|
9
|
-
config.detector :extraneous_indexes, ignore_tables: ["users"]
|
10
|
-
end
|
11
|
-
CONFIG
|
12
|
-
|
13
|
-
config = ActiveRecordDoctor.load_config(config_path)
|
14
|
-
|
15
|
-
assert_equal(
|
16
|
-
{ ignore_tables: ["schema_migrations"] },
|
17
|
-
config.globals
|
18
|
-
)
|
19
|
-
assert_equal(
|
20
|
-
{ extraneous_indexes: { ignore_tables: ["users"] } },
|
21
|
-
config.detectors
|
22
|
-
)
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_load_config_raises_when_configuration_file_missing
|
26
|
-
exc = assert_raises(ActiveRecordDoctor::Error::ConfigurationFileMissing) do
|
27
|
-
ActiveRecordDoctor.load_config("/tmp/config.rb")
|
28
|
-
end
|
29
|
-
assert_equal("/tmp/config.rb", exc.config_path)
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_load_config_raises_when_configuration_file_raises
|
33
|
-
config_path = config_file("1/0")
|
34
|
-
|
35
|
-
assert_raises(ActiveRecordDoctor::Error::ConfigurationError) do
|
36
|
-
ActiveRecordDoctor.load_config(config_path)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_load_config_raises_when_configure_not_called
|
41
|
-
config_path = config_file("# configure is not called")
|
42
|
-
|
43
|
-
assert_raises(ActiveRecordDoctor::Error::ConfigureNotCalled) do
|
44
|
-
ActiveRecordDoctor.load_config(config_path)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_load_config_raises_when_configure_called_twice
|
49
|
-
config_path = config_file(<<-CONFIG)
|
50
|
-
ActiveRecordDoctor.configure { |config| }
|
51
|
-
ActiveRecordDoctor.configure { |config| }
|
52
|
-
CONFIG
|
53
|
-
|
54
|
-
assert_raises(ActiveRecordDoctor::Error::ConfigureCalledTwice) do
|
55
|
-
ActiveRecordDoctor.load_config(config_path)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_load_config_raises_when_unrecognized_global_set
|
60
|
-
config_path = config_file(<<-CONFIG)
|
61
|
-
ActiveRecordDoctor.configure do |config|
|
62
|
-
config.global :user, "acme"
|
63
|
-
end
|
64
|
-
CONFIG
|
65
|
-
|
66
|
-
assert_raises(ActiveRecordDoctor::Error::UnrecognizedGlobalSetting) do
|
67
|
-
ActiveRecordDoctor.load_config(config_path)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_load_config_raises_when_global_set_twice
|
72
|
-
config_path = config_file(<<-CONFIG)
|
73
|
-
ActiveRecordDoctor.configure do |config|
|
74
|
-
config.global :ignore_tables, ["schema_migrations"]
|
75
|
-
config.global :ignore_tables, ["schema_migrations"]
|
76
|
-
end
|
77
|
-
CONFIG
|
78
|
-
|
79
|
-
assert_raises(ActiveRecordDoctor::Error::DuplicateGlobalSetting) do
|
80
|
-
ActiveRecordDoctor.load_config(config_path)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_load_config_raises_when_configured_unrecognized_detector
|
85
|
-
config_path = config_file(<<-CONFIG)
|
86
|
-
ActiveRecordDoctor.configure do |config|
|
87
|
-
config.detector :other_performance_issues, {}
|
88
|
-
end
|
89
|
-
CONFIG
|
90
|
-
|
91
|
-
assert_raises(ActiveRecordDoctor::Error::UnrecognizedDetectorName) do
|
92
|
-
ActiveRecordDoctor.load_config(config_path)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_load_config_raises_when_detector_configured_twice
|
97
|
-
config_path = config_file(<<-CONFIG)
|
98
|
-
ActiveRecordDoctor.configure do |config|
|
99
|
-
config.detector :extraneous_indexes, ignore_tables: ["users"]
|
100
|
-
config.detector :extraneous_indexes, ignore_tables: ["users"]
|
101
|
-
end
|
102
|
-
CONFIG
|
103
|
-
|
104
|
-
assert_raises(ActiveRecordDoctor::Error::DetectorConfiguredTwice) do
|
105
|
-
ActiveRecordDoctor.load_config(config_path)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def test_load_config_raises_when_provided_unrecognized_detector_setting
|
110
|
-
config_path = config_file(<<-CONFIG)
|
111
|
-
ActiveRecordDoctor.configure do |config|
|
112
|
-
config.detector :extraneous_indexes, { delay: 1 }
|
113
|
-
end
|
114
|
-
CONFIG
|
115
|
-
|
116
|
-
assert_raises(ActiveRecordDoctor::Error::UnrecognizedDetectorSettings) do
|
117
|
-
ActiveRecordDoctor.load_config(config_path)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|