active_record_doctor 1.8.0 → 1.10.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +316 -54
  3. data/lib/active_record_doctor/config/default.rb +76 -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 +142 -21
  7. data/lib/active_record_doctor/detectors/extraneous_indexes.rb +59 -48
  8. data/lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb +31 -23
  9. data/lib/active_record_doctor/detectors/incorrect_dependent_option.rb +102 -35
  10. data/lib/active_record_doctor/detectors/incorrect_length_validation.rb +63 -0
  11. data/lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb +45 -0
  12. data/lib/active_record_doctor/detectors/missing_foreign_keys.rb +32 -23
  13. data/lib/active_record_doctor/detectors/missing_non_null_constraint.rb +41 -28
  14. data/lib/active_record_doctor/detectors/missing_presence_validation.rb +29 -23
  15. data/lib/active_record_doctor/detectors/missing_unique_indexes.rb +92 -32
  16. data/lib/active_record_doctor/detectors/short_primary_key_type.rb +45 -0
  17. data/lib/active_record_doctor/detectors/undefined_table_references.rb +17 -20
  18. data/lib/active_record_doctor/detectors/unindexed_deleted_at.rb +43 -18
  19. data/lib/active_record_doctor/detectors/unindexed_foreign_keys.rb +31 -20
  20. data/lib/active_record_doctor/detectors.rb +12 -4
  21. data/lib/active_record_doctor/errors.rb +226 -0
  22. data/lib/active_record_doctor/help.rb +39 -0
  23. data/lib/active_record_doctor/rake/task.rb +78 -0
  24. data/lib/active_record_doctor/runner.rb +41 -0
  25. data/lib/active_record_doctor/version.rb +1 -1
  26. data/lib/active_record_doctor.rb +8 -3
  27. data/lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb +34 -21
  28. data/lib/tasks/active_record_doctor.rake +9 -18
  29. data/test/active_record_doctor/config/loader_test.rb +120 -0
  30. data/test/active_record_doctor/config_test.rb +116 -0
  31. data/test/active_record_doctor/detectors/disable_test.rb +30 -0
  32. data/test/active_record_doctor/detectors/extraneous_indexes_test.rb +165 -8
  33. data/test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb +48 -5
  34. data/test/active_record_doctor/detectors/incorrect_dependent_option_test.rb +288 -12
  35. data/test/active_record_doctor/detectors/incorrect_length_validation_test.rb +105 -0
  36. data/test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb +82 -0
  37. data/test/active_record_doctor/detectors/missing_foreign_keys_test.rb +50 -4
  38. data/test/active_record_doctor/detectors/missing_non_null_constraint_test.rb +172 -24
  39. data/test/active_record_doctor/detectors/missing_presence_validation_test.rb +111 -14
  40. data/test/active_record_doctor/detectors/missing_unique_indexes_test.rb +223 -10
  41. data/test/active_record_doctor/detectors/short_primary_key_type_test.rb +72 -0
  42. data/test/active_record_doctor/detectors/undefined_table_references_test.rb +34 -21
  43. data/test/active_record_doctor/detectors/unindexed_deleted_at_test.rb +118 -8
  44. data/test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb +56 -4
  45. data/test/active_record_doctor/runner_test.rb +42 -0
  46. data/test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb +131 -0
  47. data/test/model_factory.rb +73 -23
  48. data/test/setup.rb +65 -71
  49. metadata +43 -7
  50. data/lib/active_record_doctor/printers/io_printer.rb +0 -133
  51. data/lib/active_record_doctor/task.rb +0 -28
  52. data/test/active_record_doctor/printers/io_printer_test.rb +0 -33
data/test/setup.rb CHANGED
@@ -7,45 +7,25 @@
7
7
  require "uri"
8
8
 
9
9
  require "active_record"
10
+ require "pg"
11
+ require "mysql2"
10
12
 
11
- # Connect to the database defined in the URL.
12
- case ENV["DATABASE"]
13
- when "postgresql"
14
- require "pg"
15
- DEFAULT_DATABASE_URL = "postgres:///active_record_doctor_test"
16
- when "mysql"
17
- require "mysql2"
18
- DEFAULT_DATABASE_URL = "mysql2:///active_record_doctor_test"
19
- when nil
20
- # rubocop:disable Style/StderrPuts
21
- $stderr.puts(<<ERROR)
22
- The DATABASE environment variable is not set. It must be set before running the
23
- test suite. Valid values are "mysql" and "postgresql".
24
- ERROR
25
- # rubocop:enable Style/StderrPuts
26
- exit(1)
27
- else raise("unrecognized database #{ENV['DATABASE']}")
28
- end
29
- ActiveRecord::Base.establish_connection(ENV.fetch("DATABASE_URL", DEFAULT_DATABASE_URL))
13
+ adapter = ENV.fetch("DATABASE_ADAPTER")
14
+ ActiveRecord::Base.establish_connection(
15
+ adapter: adapter,
16
+ host: ENV["DATABASE_HOST"],
17
+ port: ENV["DATABASE_PORT"],
18
+ username: ENV["DATABASE_USERNAME"],
19
+ password: ENV["DATABASE_PASSWORD"],
20
+ database: "active_record_doctor_test"
21
+ )
22
+
23
+ puts "Using #{adapter}"
30
24
 
31
25
  # We need to call #connection to enfore Active Record to actually establish
32
26
  # the connection.
33
27
  ActiveRecord::Base.connection
34
28
 
35
- # We need to mock Rails because some detectors depend on .eager_load! This must
36
- # happen AFTER loading active_record_doctor as otherwise it'd attempt to
37
- # install a Railtie.
38
- module Rails
39
- class TestApplication
40
- def eager_load!
41
- end
42
- end
43
-
44
- def self.application
45
- @application ||= TestApplication.new
46
- end
47
- end
48
-
49
29
  # Load Active Record Doctor.
50
30
  require "active_record_doctor"
51
31
 
@@ -53,23 +33,52 @@ require "active_record_doctor"
53
33
  require "minitest"
54
34
  require "minitest/autorun"
55
35
  require "minitest/fork_executor"
56
-
57
36
  require_relative "model_factory"
58
37
 
38
+ # Filter out Minitest backtrace while allowing backtrace from other libraries
39
+ # to be shown.
40
+ Minitest.backtrace_filter = Minitest::BacktraceFilter.new
41
+
42
+ # Uncomment in case there's test case interference.
43
+ Minitest.parallel_executor = Minitest::ForkExecutor.new
44
+
59
45
  # Prepare the test class.
60
46
  class Minitest::Test
47
+ include ModelFactory
48
+
61
49
  def setup
62
- # Ensure all remnants of previous test runs, most likely in form of tables,
63
- # are removed.
64
- ModelFactory.cleanup
50
+ # Delete remnants (models and tables) of previous test case runs.
51
+ cleanup_models
65
52
  end
66
53
 
67
54
  def teardown
68
- ModelFactory.cleanup
55
+ @config_path = nil
56
+
57
+ if @previous_dir
58
+ Dir.chdir(@previous_dir)
59
+ @previous_dir = nil
60
+ end
61
+
62
+ # Ensure all remnants of previous test runs, most likely in form of tables,
63
+ # are removed.
64
+ cleanup_models
69
65
  end
70
66
 
71
67
  private
72
68
 
69
+ attr_reader :config_path
70
+
71
+ def config_file(content)
72
+ @previous_dir = Dir.pwd
73
+
74
+ directory = Dir.mktmpdir("active_record_doctor")
75
+ @config_path = File.join(directory, ".active_record_doctor")
76
+ File.write(@config_path, content)
77
+ Dir.chdir(directory)
78
+
79
+ @config_path
80
+ end
81
+
73
82
  def postgresql?
74
83
  ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
75
84
  end
@@ -78,49 +87,34 @@ class Minitest::Test
78
87
  ActiveRecord::Base.connection.adapter_name == "Mysql2"
79
88
  end
80
89
 
81
- def create_table(*args, &block)
82
- ModelFactory.create_table(*args, &block)
90
+ def detector_name
91
+ self.class.name.sub(/Test$/, "").demodulize.underscore.to_sym
83
92
  end
84
93
 
85
- def create_model(*args, &block)
86
- ModelFactory.create_model(*args, &block)
87
- end
88
-
89
- # Return the detector class under test.
90
- def detector_class
91
- self.class.name.sub(/Test$/, "").constantize
92
- end
93
-
94
- # Run the appropriate detector. The detector name is inferred from the test class.
95
94
  def run_detector
96
- detector_class.run.first
95
+ io = StringIO.new
96
+ runner = ActiveRecordDoctor::Runner.new(load_config, io)
97
+ success = runner.run_one(detector_name)
98
+ [success, io.string]
97
99
  end
98
100
 
99
- def run_task
100
- output = StringIO.new
101
- printer = ActiveRecordDoctor::Printers::IOPrinter.new(output)
102
- success = ActiveRecordDoctor::Task.new(detector_class, printer).run
103
- [success, output.string]
101
+ def load_config
102
+ ActiveRecordDoctor.load_config_with_defaults(@config_path)
104
103
  end
105
104
 
106
105
  def assert_problems(expected_output)
107
- success, actual_output = run_task
108
-
109
- assert_equal(expected_output, actual_output)
110
- refute(success)
106
+ success, output = run_detector
107
+ assert_equal(sort_lines(expected_output), sort_lines(output))
108
+ refute(success, "Expected the detector to return failure.")
111
109
  end
112
110
 
113
- def refute_problems
114
- success, actual_output = run_task
111
+ def refute_problems(expected_output = "")
112
+ success, output = run_detector
113
+ assert_equal(sort_lines(expected_output), sort_lines(output))
114
+ assert(success, "Expected the detector to return success.")
115
+ end
115
116
 
116
- assert_equal("", actual_output)
117
- assert(success)
117
+ def sort_lines(string)
118
+ string.split("\n").sort.join("\n")
118
119
  end
119
120
  end
120
-
121
- # Filter out Minitest backtrace while allowing backtrace from other libraries
122
- # to be shown.
123
- Minitest.backtrace_filter = Minitest::BacktraceFilter.new
124
-
125
- # Uncomment in case there's test case interference.
126
- Minitest.parallel_executor = Minitest::ForkExecutor.new
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.8.0
4
+ version: 1.10.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: 2021-05-20 00:00:00.000000000 Z
11
+ date: 2022-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.1.4
69
+ - !ruby/object:Gem::Dependency
70
+ name: railties
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 4.2.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 4.2.0
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -104,37 +118,52 @@ files:
104
118
  - MIT-LICENSE.txt
105
119
  - README.md
106
120
  - lib/active_record_doctor.rb
121
+ - lib/active_record_doctor/config.rb
122
+ - lib/active_record_doctor/config/default.rb
123
+ - lib/active_record_doctor/config/loader.rb
107
124
  - lib/active_record_doctor/detectors.rb
108
125
  - lib/active_record_doctor/detectors/base.rb
109
126
  - lib/active_record_doctor/detectors/extraneous_indexes.rb
110
127
  - lib/active_record_doctor/detectors/incorrect_boolean_presence_validation.rb
111
128
  - lib/active_record_doctor/detectors/incorrect_dependent_option.rb
129
+ - lib/active_record_doctor/detectors/incorrect_length_validation.rb
130
+ - lib/active_record_doctor/detectors/mismatched_foreign_key_type.rb
112
131
  - lib/active_record_doctor/detectors/missing_foreign_keys.rb
113
132
  - lib/active_record_doctor/detectors/missing_non_null_constraint.rb
114
133
  - lib/active_record_doctor/detectors/missing_presence_validation.rb
115
134
  - lib/active_record_doctor/detectors/missing_unique_indexes.rb
135
+ - lib/active_record_doctor/detectors/short_primary_key_type.rb
116
136
  - lib/active_record_doctor/detectors/undefined_table_references.rb
117
137
  - lib/active_record_doctor/detectors/unindexed_deleted_at.rb
118
138
  - lib/active_record_doctor/detectors/unindexed_foreign_keys.rb
139
+ - lib/active_record_doctor/errors.rb
140
+ - lib/active_record_doctor/help.rb
119
141
  - lib/active_record_doctor/printers.rb
120
- - lib/active_record_doctor/printers/io_printer.rb
121
142
  - lib/active_record_doctor/railtie.rb
122
- - lib/active_record_doctor/task.rb
143
+ - lib/active_record_doctor/rake/task.rb
144
+ - lib/active_record_doctor/runner.rb
123
145
  - lib/active_record_doctor/version.rb
124
146
  - lib/generators/active_record_doctor/add_indexes/USAGE
125
147
  - lib/generators/active_record_doctor/add_indexes/add_indexes_generator.rb
126
148
  - lib/tasks/active_record_doctor.rake
149
+ - test/active_record_doctor/config/loader_test.rb
150
+ - test/active_record_doctor/config_test.rb
151
+ - test/active_record_doctor/detectors/disable_test.rb
127
152
  - test/active_record_doctor/detectors/extraneous_indexes_test.rb
128
153
  - test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb
129
154
  - test/active_record_doctor/detectors/incorrect_dependent_option_test.rb
155
+ - test/active_record_doctor/detectors/incorrect_length_validation_test.rb
156
+ - test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb
130
157
  - test/active_record_doctor/detectors/missing_foreign_keys_test.rb
131
158
  - test/active_record_doctor/detectors/missing_non_null_constraint_test.rb
132
159
  - test/active_record_doctor/detectors/missing_presence_validation_test.rb
133
160
  - test/active_record_doctor/detectors/missing_unique_indexes_test.rb
161
+ - test/active_record_doctor/detectors/short_primary_key_type_test.rb
134
162
  - test/active_record_doctor/detectors/undefined_table_references_test.rb
135
163
  - test/active_record_doctor/detectors/unindexed_deleted_at_test.rb
136
164
  - test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb
137
- - test/active_record_doctor/printers/io_printer_test.rb
165
+ - test/active_record_doctor/runner_test.rb
166
+ - test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb
138
167
  - test/model_factory.rb
139
168
  - test/setup.rb
140
169
  homepage: https://github.com/gregnavis/active_record_doctor
@@ -156,21 +185,28 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
185
  - !ruby/object:Gem::Version
157
186
  version: '0'
158
187
  requirements: []
159
- rubygems_version: 3.2.15
188
+ rubygems_version: 3.2.33
160
189
  signing_key:
161
190
  specification_version: 4
162
191
  summary: Identify database issues before they hit production.
163
192
  test_files:
193
+ - test/active_record_doctor/config/loader_test.rb
194
+ - test/active_record_doctor/config_test.rb
195
+ - test/active_record_doctor/detectors/disable_test.rb
164
196
  - test/active_record_doctor/detectors/extraneous_indexes_test.rb
165
197
  - test/active_record_doctor/detectors/incorrect_boolean_presence_validation_test.rb
166
198
  - test/active_record_doctor/detectors/incorrect_dependent_option_test.rb
199
+ - test/active_record_doctor/detectors/incorrect_length_validation_test.rb
200
+ - test/active_record_doctor/detectors/mismatched_foreign_key_type_test.rb
167
201
  - test/active_record_doctor/detectors/missing_foreign_keys_test.rb
168
202
  - test/active_record_doctor/detectors/missing_non_null_constraint_test.rb
169
203
  - test/active_record_doctor/detectors/missing_presence_validation_test.rb
170
204
  - test/active_record_doctor/detectors/missing_unique_indexes_test.rb
205
+ - test/active_record_doctor/detectors/short_primary_key_type_test.rb
171
206
  - test/active_record_doctor/detectors/undefined_table_references_test.rb
172
207
  - test/active_record_doctor/detectors/unindexed_deleted_at_test.rb
173
208
  - test/active_record_doctor/detectors/unindexed_foreign_keys_test.rb
174
- - test/active_record_doctor/printers/io_printer_test.rb
209
+ - test/active_record_doctor/runner_test.rb
210
+ - test/generators/active_record_doctor/add_indexes/add_indexes_generator_test.rb
175
211
  - test/model_factory.rb
176
212
  - test/setup.rb
@@ -1,133 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecordDoctor
4
- module Printers
5
- # Default printer for displaying messages produced by active_record_doctor.
6
- class IOPrinter
7
- def initialize(io = $stdout)
8
- @io = io
9
- end
10
-
11
- def unindexed_foreign_keys(unindexed_foreign_keys, _options)
12
- return if unindexed_foreign_keys.empty?
13
-
14
- @io.puts("The following foreign keys should be indexed for performance reasons:")
15
- @io.puts(unindexed_foreign_keys.sort.map do |table, columns|
16
- " #{table} #{columns.sort.join(' ')}"
17
- end.join("\n"))
18
- end
19
-
20
- def extraneous_indexes(extraneous_indexes, _options)
21
- return if extraneous_indexes.empty?
22
-
23
- @io.puts("The following indexes are extraneous and can be removed:")
24
- extraneous_indexes.each do |index, details|
25
- reason, *params = details
26
- case reason
27
- when :multi_column
28
- @io.puts(" #{index} (can be handled by #{params.join(', ')})")
29
- when :primary_key
30
- @io.puts(" #{index} (is a primary key of #{params[0]})")
31
- else
32
- raise("unknown reason #{reason.inspect}")
33
- end
34
- end
35
- end
36
-
37
- def missing_foreign_keys(missing_foreign_keys, _options)
38
- return if missing_foreign_keys.empty?
39
-
40
- @io.puts("The following columns lack a foreign key constraint:")
41
- @io.puts(missing_foreign_keys.sort.map do |table, columns|
42
- " #{table} #{columns.sort.join(' ')}"
43
- end.join("\n"))
44
- end
45
-
46
- def undefined_table_references(models, options)
47
- return if models.empty?
48
-
49
- unless options.fetch(:views_checked)
50
- @io.puts(<<WARNING)
51
- WARNING: Models backed by database views are supported only in Rails 5+ OR
52
- Rails 4.2 + PostgreSQL. It seems this is NOT your setup. Therefore, such models
53
- will be erroneously reported below as not having their underlying tables/views.
54
- Consider upgrading Rails or disabling this task temporarily.
55
- WARNING
56
- end
57
-
58
- @io.puts("The following models reference undefined tables:")
59
- models.each do |model_name, table_name|
60
- @io.puts(" #{model_name} (the table #{table_name} is undefined)")
61
- end
62
- end
63
-
64
- def unindexed_deleted_at(indexes, _options)
65
- return if indexes.empty?
66
-
67
- @io.puts("The following indexes should include `deleted_at IS NULL`:")
68
- indexes.each do |index|
69
- @io.puts(" #{index}")
70
- end
71
- end
72
-
73
- def missing_unique_indexes(indexes, _options)
74
- return if indexes.empty?
75
-
76
- @io.puts("The following indexes should be created to back model-level uniqueness validations:")
77
- indexes.each do |table, arrays_of_columns|
78
- arrays_of_columns.each do |columns|
79
- @io.puts(" #{table}: #{columns.join(', ')}")
80
- end
81
- end
82
- end
83
-
84
- def missing_presence_validation(missing_presence_validators, _options)
85
- return if missing_presence_validators.empty?
86
-
87
- @io.puts("The following models and columns should have presence validations:")
88
- missing_presence_validators.each do |model_name, array_of_columns|
89
- @io.puts(" #{model_name}: #{array_of_columns.join(', ')}")
90
- end
91
- end
92
-
93
- def missing_non_null_constraint(missing_non_null_constraints, _options)
94
- return if missing_non_null_constraints.empty?
95
-
96
- @io.puts("The following columns should be marked as `null: false`:")
97
- missing_non_null_constraints.each do |table, columns|
98
- @io.puts(" #{table}: #{columns.join(', ')}")
99
- end
100
- end
101
-
102
- def incorrect_boolean_presence_validation(incorrect_boolean_presence_validations, _options)
103
- return if incorrect_boolean_presence_validations.empty?
104
-
105
- @io.puts("The presence of the following boolean columns is validated incorrectly:")
106
- incorrect_boolean_presence_validations.each do |table, columns|
107
- @io.puts(" #{table}: #{columns.join(', ')}")
108
- end
109
- end
110
-
111
- def incorrect_dependent_option(problems, _options)
112
- return if problems.empty?
113
-
114
- @io.puts("The following associations might be using invalid dependent settings:")
115
- problems.each do |model, associations|
116
- associations.each do |(name, problem)|
117
- # rubocop:disable Layout/LineLength
118
- message =
119
- case problem
120
- when :suggest_destroy then "skips callbacks that are defined on the associated model - consider changing to `dependent: :destroy` or similar"
121
- when :suggest_delete then "loads the associated model before deleting it - consider using `dependent: :delete`"
122
- when :suggest_delete_all then "loads models one-by-one to invoke callbacks even though the related model defines none - consider using `dependent: :delete_all`"
123
- else next
124
- end
125
- # rubocop:enable Layout/LineLength
126
-
127
- @io.puts(" #{model}: #{name} #{message}")
128
- end
129
- end
130
- end
131
- end
132
- end
133
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecordDoctor
4
- # Rake task for running a detector and reporting its results.
5
- class Task
6
- DEFAULT_PRINTER = ActiveRecordDoctor::Printers::IOPrinter.new
7
-
8
- def initialize(detector_class, printer = DEFAULT_PRINTER)
9
- @detector_class = detector_class
10
- @printer = printer
11
- end
12
-
13
- def name
14
- @detector_class.name.demodulize.underscore.to_sym
15
- end
16
-
17
- def description
18
- @detector_class.description
19
- end
20
-
21
- def run
22
- problems, options = @detector_class.run
23
- @printer.public_send(name, problems, options)
24
-
25
- problems.empty?
26
- end
27
- end
28
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Load all detectors
4
- class ActiveRecordDoctor::Printers::IOPrinterTest < Minitest::Test
5
- def test_all_detectors_have_printers
6
- ActiveRecordDoctor::Detectors::Base.subclasses.each do |detector_class|
7
- name = detector_class.name.demodulize.underscore.to_sym
8
-
9
- assert(
10
- ActiveRecordDoctor::Printers::IOPrinter.method_defined?(name),
11
- "IOPrinter should define #{name}"
12
- )
13
- end
14
- end
15
-
16
- def test_unindexed_foreign_keys
17
- # rubocop:disable Layout/LineLength
18
- assert_equal(<<OUTPUT, unindexed_foreign_keys({ "users" => ["profile_id", "account_id"], "account" => ["group_id"] }))
19
- The following foreign keys should be indexed for performance reasons:
20
- account group_id
21
- users account_id profile_id
22
- OUTPUT
23
- # rubocop:enable Layout/LineLength
24
- end
25
-
26
- private
27
-
28
- def unindexed_foreign_keys(argument)
29
- io = StringIO.new
30
- ActiveRecordDoctor::Printers::IOPrinter.new(io).unindexed_foreign_keys(argument, {})
31
- io.string
32
- end
33
- end