active_record_doctor 1.11.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -14
  3. data/lib/active_record_doctor/config/loader.rb +1 -1
  4. data/lib/active_record_doctor/detectors/base.rb +30 -15
  5. data/lib/active_record_doctor/detectors/extraneous_indexes.rb +14 -9
  6. data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +1 -1
  7. data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +44 -31
  8. data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +1 -1
  9. data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +2 -2
  10. data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +73 -23
  11. data/lib/active_record_doctor/detectors/short_primary_key_type.rb +3 -3
  12. data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +34 -7
  13. data/lib/active_record_doctor/logger/hierarchical.rb +1 -1
  14. data/lib/active_record_doctor/railtie.rb +1 -1
  15. data/lib/active_record_doctor/runner.rb +1 -1
  16. data/lib/active_record_doctor/utils.rb +21 -0
  17. data/lib/active_record_doctor/version.rb +1 -1
  18. data/lib/active_record_doctor.rb +2 -0
  19. data/lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb +14 -14
  20. data/lib/tasks/active_record_doctor.rake +2 -2
  21. metadata +11 -47
  22. data/test/active_record_doctor/config/loader_test.rb +0 -120
  23. data/test/active_record_doctor/config_test.rb +0 -116
  24. data/test/active_record_doctor/detectors/disable_test.rb +0 -30
  25. data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +0 -224
  26. data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +0 -79
  27. data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +0 -472
  28. data/test/active_record_doctor/detectors/incorrect_length_validation_test.rb +0 -107
  29. data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +0 -116
  30. data/test/active_record_doctor/detectors/missing_foreign_keys_test.rb +0 -70
  31. data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +0 -273
  32. data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +0 -232
  33. data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +0 -327
  34. data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +0 -72
  35. data/test/active_record_doctor/detectors/undefined_table_references_test.rb +0 -55
  36. data/test/active_record_doctor/detectors/unindexed_deleted_at_test.rb +0 -177
  37. data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +0 -78
  38. data/test/active_record_doctor/runner_test.rb +0 -41
  39. data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +0 -131
  40. data/test/setup.rb +0 -124
@@ -18,28 +18,44 @@ module ActiveRecordDoctor
18
18
 
19
19
  private
20
20
 
21
- def message(table:, column:)
21
+ def message(table:, columns:)
22
22
  # rubocop:disable Layout/LineLength
23
- "add an index on #{table}.#{column} - foreign keys are often used in database lookups and should be indexed for performance reasons"
23
+ "add an index on #{table}(#{columns.join(', ')}) - foreign keys are often used in database lookups and should be indexed for performance reasons"
24
24
  # rubocop:enable Layout/LineLength
25
25
  end
26
26
 
27
27
  def detect
28
28
  each_table(except: config(:ignore_tables)) do |table|
29
29
  each_column(table, except: config(:ignore_columns)) do |column|
30
- next unless foreign_key?(column)
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
- problem!(table: table, column: column.name)
35
+ type_column_name = type_column_name(column)
36
+
37
+ columns =
38
+ if column_exists?(table, type_column_name)
39
+ [type_column_name, column.name]
40
+ else
41
+ [column.name]
42
+ end
43
+
44
+ problem!(table: table, columns: columns)
35
45
  end
36
46
  end
37
47
  end
38
48
 
39
- def foreign_key?(column)
49
+ def named_like_foreign_key?(column)
40
50
  column.name.end_with?("_id")
41
51
  end
42
52
 
53
+ def foreign_key?(table, column)
54
+ connection.foreign_keys(table).any? do |foreign_key|
55
+ foreign_key.column == column.name
56
+ end
57
+ end
58
+
43
59
  def indexed?(table, column)
44
60
  connection.indexes(table).any? do |index|
45
61
  index.columns.first == column.name
@@ -47,9 +63,20 @@ module ActiveRecordDoctor
47
63
  end
48
64
 
49
65
  def indexed_as_polymorphic?(table, column)
50
- type_column_name = column.name.sub(/_id\Z/, "_type")
51
66
  connection.indexes(table).any? do |index|
52
- index.columns == [type_column_name, column.name]
67
+ index.columns[0, 2] == [type_column_name(column), column.name]
68
+ end
69
+ end
70
+
71
+ def column_exists?(table, column_name)
72
+ connection.columns(table).any? { |column| column.name == column_name }
73
+ end
74
+
75
+ def type_column_name(column)
76
+ if column.name.end_with?("_id")
77
+ column.name.sub(/_id\Z/, "_type")
78
+ else
79
+ "#{column.name}_type"
53
80
  end
54
81
  end
55
82
  end
@@ -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
@@ -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.
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordDoctor
4
+ module Utils # :nodoc:
5
+ class << self
6
+ def postgresql?(connection = ActiveRecord::Base.connection)
7
+ ["PostgreSQL", "PostGIS"].include?(connection.adapter_name)
8
+ end
9
+
10
+ def mysql?(connection = ActiveRecord::Base.connection)
11
+ connection.adapter_name == "Mysql2"
12
+ end
13
+
14
+ def expression_indexes_unsupported?(connection = ActiveRecord::Base.connection)
15
+ (ActiveRecord::VERSION::STRING < "5.0") ||
16
+ # Active Record is unable to correctly parse expression indexes for MySQL.
17
+ (mysql?(connection) && ActiveRecord::VERSION::STRING < "7.1")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordDoctor
4
- VERSION = "1.11.0"
4
+ VERSION = "1.13.0"
5
5
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_record_doctor/railtie" if defined?(Rails) && defined?(Rails::Railtie)
4
+ require "active_record_doctor/utils"
4
5
  require "active_record_doctor/logger"
5
6
  require "active_record_doctor/logger/dummy"
6
7
  require "active_record_doctor/logger/hierarchical"
@@ -25,6 +26,7 @@ require "active_record_doctor/runner"
25
26
  require "active_record_doctor/version"
26
27
  require "active_record_doctor/config"
27
28
  require "active_record_doctor/config/loader"
29
+ require "active_record_doctor/rake/task"
28
30
 
29
31
  module ActiveRecordDoctor # :nodoc:
30
32
  end
@@ -10,16 +10,16 @@ module ActiveRecordDoctor
10
10
  migration_descriptions = read_migration_descriptions(path)
11
11
  now = Time.now
12
12
 
13
- migration_descriptions.each_with_index do |(table, columns), index|
13
+ migration_descriptions.each_with_index do |(table, indexes), index|
14
14
  timestamp = (now + index).strftime("%Y%m%d%H%M%S")
15
15
  file_name = "db/migrate/#{timestamp}_index_foreign_keys_in_#{table}.rb"
16
- create_file(file_name, content(table, columns).tap { |x| puts x })
16
+ create_file(file_name, content(table, indexes).tap { |x| puts x })
17
17
  end
18
18
  end
19
19
 
20
20
  private
21
21
 
22
- INPUT_LINE = /^add an index on (\w+)\.(\w+) - .*$/.freeze
22
+ INPUT_LINE = /^add an index on (\w+)\((.+)\) - .*$/.freeze
23
23
  private_constant :INPUT_LINE
24
24
 
25
25
  def read_migration_descriptions(path)
@@ -34,41 +34,41 @@ module ActiveRecordDoctor
34
34
  end
35
35
 
36
36
  table = match[1]
37
- column = match[2]
37
+ columns = match[2].split(",").map(&:strip)
38
38
 
39
- tables_to_columns[table] << column
39
+ tables_to_columns[table] << columns
40
40
  end
41
41
 
42
42
  tables_to_columns
43
43
  end
44
44
 
45
- def content(table, columns)
45
+ def content(table, indexes)
46
46
  # In order to properly indent the resulting code, we must disable the
47
47
  # rubocop rule below.
48
48
 
49
49
  <<MIGRATION
50
50
  class IndexForeignKeysIn#{table.camelize} < ActiveRecord::Migration#{migration_version}
51
51
  def change
52
- #{add_indexes(table, columns)}
52
+ #{add_indexes(table, indexes)}
53
53
  end
54
54
  end
55
55
  MIGRATION
56
56
  end
57
57
 
58
- def add_indexes(table, columns)
59
- columns.map do |column|
60
- add_index(table, column)
58
+ def add_indexes(table, indexes)
59
+ indexes.map do |columns|
60
+ add_index(table, columns)
61
61
  end.join("\n")
62
62
  end
63
63
 
64
- def add_index(table, column)
64
+ def add_index(table, columns)
65
65
  connection = ActiveRecord::Base.connection
66
66
 
67
- index_name = connection.index_name(table, column)
67
+ index_name = connection.index_name(table, columns)
68
68
  if index_name.size > connection.index_name_length
69
- " add_index :#{table}, :#{column}, name: '#{index_name.first(connection.index_name_length)}'"
69
+ " add_index :#{table}, #{columns.inspect}, name: '#{index_name.first(connection.index_name_length)}'"
70
70
  else
71
- " add_index :#{table}, :#{column}"
71
+ " add_index :#{table}, #{columns.inspect}"
72
72
  end
73
73
  end
74
74
 
@@ -19,6 +19,6 @@ 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.config_path = Rails.root.join(".active_record_doctor")
23
+ task.setup = -> { Rails.application.eager_load! }
24
24
  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.11.0
4
+ version: 1.13.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-03-16 00:00:00.000000000 Z
11
+ date: 2023-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -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
@@ -159,33 +159,16 @@ files:
159
159
  - lib/active_record_doctor/railtie.rb
160
160
  - lib/active_record_doctor/rake/task.rb
161
161
  - lib/active_record_doctor/runner.rb
162
+ - lib/active_record_doctor/utils.rb
162
163
  - lib/active_record_doctor/version.rb
163
164
  - lib/generators/active_record_doctor/add_indexes/USAGE
164
165
  - lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb
165
166
  - lib/tasks/active_record_doctor.rake
166
- - test/active_record_doctor/config/loader_test.rb
167
- - test/active_record_doctor/config_test.rb
168
- - test/active_record_doctor/detectors/disable_test.rb
169
- - test/active_record_doctor/detectors/extraneous_indexes_test.rb
170
- - test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb
171
- - test/active_record_doctor/detectors/incorrect_dependent_option_test.rb
172
- - test/active_record_doctor/detectors/incorrect_length_validation_test.rb
173
- - test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb
174
- - test/active_record_doctor/detectors/missing_foreign_keys_test.rb
175
- - test/active_record_doctor/detectors/missing_non_null_constraint_test.rb
176
- - test/active_record_doctor/detectors/missing_presence_validation_test.rb
177
- - test/active_record_doctor/detectors/missing_unique_indexes_test.rb
178
- - test/active_record_doctor/detectors/short_primary_key_type_test.rb
179
- - test/active_record_doctor/detectors/undefined_table_references_test.rb
180
- - test/active_record_doctor/detectors/unindexed_deleted_at_test.rb
181
- - test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb
182
- - test/active_record_doctor/runner_test.rb
183
- - test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb
184
- - test/setup.rb
185
167
  homepage: https://github.com/gregnavis/active_record_doctor
186
168
  licenses:
187
169
  - MIT
188
- metadata: {}
170
+ metadata:
171
+ rubygems_mfa_required: 'true'
189
172
  post_install_message:
190
173
  rdoc_options: []
191
174
  require_paths:
@@ -201,27 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
184
  - !ruby/object:Gem::Version
202
185
  version: '0'
203
186
  requirements: []
204
- rubygems_version: 3.2.33
187
+ rubygems_version: 3.3.26
205
188
  signing_key:
206
189
  specification_version: 4
207
190
  summary: Identify database issues before they hit production.
208
- test_files:
209
- - test/active_record_doctor/config/loader_test.rb
210
- - test/active_record_doctor/config_test.rb
211
- - test/active_record_doctor/detectors/disable_test.rb
212
- - test/active_record_doctor/detectors/extraneous_indexes_test.rb
213
- - test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb
214
- - test/active_record_doctor/detectors/incorrect_dependent_option_test.rb
215
- - test/active_record_doctor/detectors/incorrect_length_validation_test.rb
216
- - test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb
217
- - test/active_record_doctor/detectors/missing_foreign_keys_test.rb
218
- - test/active_record_doctor/detectors/missing_non_null_constraint_test.rb
219
- - test/active_record_doctor/detectors/missing_presence_validation_test.rb
220
- - test/active_record_doctor/detectors/missing_unique_indexes_test.rb
221
- - test/active_record_doctor/detectors/short_primary_key_type_test.rb
222
- - test/active_record_doctor/detectors/undefined_table_references_test.rb
223
- - test/active_record_doctor/detectors/unindexed_deleted_at_test.rb
224
- - test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb
225
- - test/active_record_doctor/runner_test.rb
226
- - test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb
227
- - 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
@@ -1,116 +0,0 @@
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
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ActiveRecordDoctor::Detectors::DisableTest < Minitest::Test
4
- # Disabling detectors is implemented in the base class. It's enought to test
5
- # it on a single detector to be reasonably certain it works on all of them.
6
- def test_disabling
7
- create_table(:users) do |t|
8
- t.string :name, null: true
9
- end.define_model do
10
- validates :name, presence: true
11
- end
12
-
13
- config_file(<<-CONFIG)
14
- ActiveRecordDoctor.configure do |config|
15
- config.detector :missing_non_null_constraint,
16
- enabled: false
17
- end
18
- CONFIG
19
-
20
- refute_problems
21
- end
22
-
23
- private
24
-
25
- # We need to override that method in order to skip the mechanism that
26
- # infers detector name from the test class name.
27
- def detector_name
28
- :missing_non_null_constraint
29
- end
30
- end