active_record_doctor 1.12.0 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +29 -2
  3. data/lib/active_record_doctor/config/loader.rb +1 -1
  4. data/lib/active_record_doctor/detectors/base.rb +11 -7
  5. data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +1 -1
  6. data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +9 -4
  7. data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +1 -1
  8. data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +2 -2
  9. data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +16 -7
  10. data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +1 -0
  11. data/lib/active_record_doctor/logger/hierarchical.rb +1 -1
  12. data/lib/active_record_doctor/railtie.rb +1 -1
  13. data/lib/active_record_doctor/rake/task.rb +35 -3
  14. data/lib/active_record_doctor/runner.rb +1 -1
  15. data/lib/active_record_doctor/utils.rb +2 -2
  16. data/lib/active_record_doctor/version.rb +1 -1
  17. data/lib/tasks/active_record_doctor.rake +1 -2
  18. metadata +12 -49
  19. data/test/active_record_doctor/config/loader_test.rb +0 -120
  20. data/test/active_record_doctor/config_test.rb +0 -116
  21. data/test/active_record_doctor/detectors/disable_test.rb +0 -30
  22. data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +0 -277
  23. data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +0 -79
  24. data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +0 -511
  25. data/test/active_record_doctor/detectors/incorrect_length_validation_test.rb +0 -107
  26. data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +0 -116
  27. data/test/active_record_doctor/detectors/missing_foreign_keys_test.rb +0 -70
  28. data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +0 -273
  29. data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +0 -232
  30. data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +0 -496
  31. data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +0 -77
  32. data/test/active_record_doctor/detectors/undefined_table_references_test.rb +0 -55
  33. data/test/active_record_doctor/detectors/unindexed_deleted_at_test.rb +0 -177
  34. data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +0 -116
  35. data/test/active_record_doctor/runner_test.rb +0 -41
  36. data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +0 -141
  37. data/test/setup.rb +0 -124
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d848e296c39f7994781bd645261eb45235450be36058fbdf7368ec6358ebeba5
4
- data.tar.gz: a63cbbfe5b43fb3bf6daeaba24a6298073643d5b5c96696c27c084106fe54594
3
+ metadata.gz: 89e283c2844a768587302646735a080d8db2b3514775083cc6bc74a25e7aff18
4
+ data.tar.gz: 975a75da213c565dba3ee7918ffe64d5b75d812059b8080d6a5134a2fb27028f
5
5
  SHA512:
6
- metadata.gz: 47411eea54d4c21329459dc7490090a535c53e9f3be912268ceed2f6e2588246cb07c9b90e758559d9b0c08de319f3dc6a4735c79511bc30c2ec7b058104c08e
7
- data.tar.gz: 9596cb799a4346b3ec60562876750990b486efc7daebfda0834b028bf2db9075f04bf6b028185df6076ede3a7227cb9755a6ac9e8db609431d063261f3c0732d
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 mutliple times via the user
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 except.include?(model.name)
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 except.include?(index.name)
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 except.include?("#{model.name}.#{column.name}")
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 except.include?("#{table_name}.#{column.name}")
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 except.include?(table)
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 except.include?(data_source)
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 except.include?("#{model.name}.#{association.name}")
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 persence (instead of inclusion) validators on boolean columns"
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
- "associated models will be deleted in the same transaction along with #{model}"
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!(model: model.name, association: association.name,
100
- table_name: foreign_key.from_table, column_name: foreign_key.column, problem: :destroy_async)
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 config(:ignore_columns).include?("#{table}.#{from_column.name}")
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).include?(table)
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 config(:ignore_columns).include?("#{table}.#{column.name}")
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
- "without an expression index can lead to duplicates (a regular unique index is not enough)"
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!(model: model, table: model.table_name, columns: columns,
74
- problem: :case_insensitive_validations)
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 config(:ignore_models).include?(has_one.klass.name)
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 ignore_columns.include?("#{model.name}(#{columns.join(',')})")
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.gsub(" ", "")
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
 
@@ -9,7 +9,7 @@ module ActiveRecordDoctor
9
9
  end
10
10
 
11
11
  def log(message)
12
- @io.puts(" " * @nesting + message.to_s)
12
+ @io.puts((" " * @nesting) + message.to_s)
13
13
  return if !block_given?
14
14
 
15
15
  @nesting += 1
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordDoctor
4
- class Railtie < Rails::Railtie
4
+ class Railtie < Rails::Railtie # :nodoc:
5
5
  rake_tasks do
6
6
  load "tasks/active_record_doctor.rake"
7
7
  end
@@ -68,9 +68,41 @@ module ActiveRecordDoctor
68
68
  end
69
69
 
70
70
  def config
71
- @config ||= begin
72
- path = config_path && File.exist?(config_path) ? config_path : nil
73
- ActiveRecordDoctor.load_config_with_defaults(path)
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 excecution environment for active_record_doctor that provides a config
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 < 6 is unable to correctly parse expression indexes for MySQL.
17
- (mysql?(connection) && ActiveRecord::VERSION::STRING < "6.0")
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordDoctor
4
- VERSION = "1.12.0"
4
+ VERSION = "1.14.0"
5
5
  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.config_path = ::Rails.root.join(".active_record_doctor")
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.12.0
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-07-27 00:00:00.000000000 Z
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.3.0
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.3.0
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: 1.0.0.rc1
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: 1.0.0.rc1
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.14.0
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.14.0
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.4.10
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