active_record_doctor 2.0.1 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94e700a1c78ee5e9657d1107578c2932a84acba7f592ab6a416e5c063520a311
4
- data.tar.gz: 8496adb8a597250ec95276fc9fbad50397667f7de2336f80405203b3a3c2a459
3
+ metadata.gz: 7c93e45a93d9c11392978f37626379bd322e4827aac59ca6f51400e33a009813
4
+ data.tar.gz: e3e920647f6b68fdec23d7e23e7e4ff3653cb8823673e56b0916d1247cbb3864
5
5
  SHA512:
6
- metadata.gz: 79803ef2db49147fdf2daf5983a3f36fb895704d150347442bebdc192a6980ecb8cd438c23fe335941284e0a39aee8c3e1a725bfe3845c7a0d3dde03830068dc
7
- data.tar.gz: 2feb5b594c369dc3d39e0f85540724474e5caa7573e0d0f18a5dcddd63d12113ec4c670ef374b475f237bd3d75fe7281bca0b0d219aac6582cbddbe59bdc2340
6
+ metadata.gz: 54c002741991dc91c4afd46de5472d64be0ba02457d23df39bd16297a12f4192023679d281d9bc353a5de5a0c357ea960666967d820316fe5fdaceee36f99d6d
7
+ data.tar.gz: bb17cb57cc708b9d7e751bb79e341aac2df4de4adc5f59d2cf254ef564c0a481b8e8872f1eac34a37246eda9145a78abbb41511150bc064932504645e36453fd
data/README.md CHANGED
@@ -17,6 +17,7 @@ can detect:
17
17
  * mismatched foreign key types - [`active_record_doctor:mismatched_foreign_key_type`](#detecting-mismatched-foreign-key-types)
18
18
  * tables without primary keys - [`active_record_doctor:table_without_primary_key`](#detecting-tables-without-primary-keys)
19
19
  * tables without timestamps - [`active_record_doctor:table_without_timestamps`](#detecting-tables-without-timestamps)
20
+ * unused tables - [`active_record_doctor:unused_tables](#detecting-unused-tables)
20
21
 
21
22
  It can also:
22
23
 
@@ -665,15 +666,35 @@ Supported configuration options:
665
666
  - `enabled` - set to `false` to disable the detector altogether
666
667
  - `ignore_tables` - tables whose timestamp columns existence should not be checked
667
668
 
668
- ## Ruby and Rails Compatibility Policy
669
+ ### Detecting Unused Tables
670
+
671
+ **WARNING**: this detector is disabled by default and has to be turned on explicitly.
672
+
673
+ When a table is not used by the application it should usually be dropped from the database.
674
+
675
+ Running the command below will list all tables that are not referenced by any model:
676
+
677
+ ```
678
+ bundle exec rake active_record_doctor:unused_tables
679
+ ```
680
+
681
+ The output of the command looks like this:
682
+
683
+ ```
684
+ The users table is not referenced by any Rails model and can be dropped
685
+ ```
669
686
 
670
- The goal of the policy is to ensure proper functioning in reasonable
671
- combinations of Ruby and Rails versions. Specifically:
687
+ Supported configuration options:
688
+
689
+ - `enabled` - set to `true` to enable the detector
690
+ - `ignore_tables` - tables that are not represented by models but cannot yet be dropped from the database (i.e. because the deployed version of the code may still be reading it)
691
+
692
+ ## Ruby and Rails Compatibility Policy
672
693
 
673
- 1. If a Rails version is officially supported by the Rails Core Team then it's
694
+ 1. `active_record_doctor` supports all Ruby on Rails versions that are supported
695
+ by the Rails core team.
696
+ 2. If a Ruby version is compatible with a supported Rails version then it's also
674
697
  supported by `active_record_doctor`.
675
- 2. If a Ruby version is compatible with a supported Rails version then it's
676
- also supported by `active_record_doctor`.
677
698
  3. Only the most recent teeny Ruby versions and patch Rails versions are supported.
678
699
 
679
700
  ## Author
@@ -83,4 +83,8 @@ ActiveRecordDoctor.configure do
83
83
  enabled: true,
84
84
  ignore_tables: [],
85
85
  ignore_columns: []
86
+
87
+ detector :unused_tables,
88
+ enabled: false,
89
+ ignore_tables: []
86
90
  end
@@ -18,9 +18,12 @@ module ActiveRecordDoctor
18
18
 
19
19
  private
20
20
 
21
- def message(model:, attribute:, table:, database_maximum:, model_maximum:)
21
+ def message(model:, column:, table:, database_maximum:, model_maximum:)
22
+ attribute = column.name
22
23
  # rubocop:disable Layout/LineLength
23
- if database_maximum && model_maximum
24
+ if database_maximum && column.respond_to?(:array?) && column.array?
25
+ "the schema limits each #{table}.#{attribute} array element to #{database_maximum} characters - use a custom validation for this attribute or add it to the ignore list"
26
+ elsif database_maximum && model_maximum
24
27
  "the schema limits #{table}.#{attribute} to #{database_maximum} characters but the length validator on #{model}.#{attribute} enforces a maximum of #{model_maximum} characters - set both limits to the same value or remove both"
25
28
  elsif database_maximum && model_maximum.nil?
26
29
  "the schema limits #{table}.#{attribute} to #{database_maximum} characters but there's no length validator on #{model}.#{attribute} - remove the database limit or add the validator"
@@ -40,7 +43,7 @@ module ActiveRecordDoctor
40
43
 
41
44
  problem!(
42
45
  model: model.name,
43
- attribute: column.name,
46
+ column: column,
44
47
  table: model.table_name,
45
48
  database_maximum: database_maximum,
46
49
  model_maximum: model_maximum
@@ -93,14 +93,14 @@ module ActiveRecordDoctor
93
93
  when ActiveModel::Validations::InclusionValidator
94
94
  validator_items = inclusion_or_exclusion_validator_items(validator)
95
95
  (validator.attributes & attribute_names).present? &&
96
- (validator_items.is_a?(Proc) || validator_items.exclude?(nil))
96
+ (dynamic_validator_items?(validator_items) || validator_items.exclude?(nil))
97
97
 
98
98
  # An exclusion validator ensures the column is not nil if it covers
99
99
  # the column and excludes nil as an allowed value explicitly.
100
100
  when ActiveModel::Validations::ExclusionValidator
101
101
  validator_items = inclusion_or_exclusion_validator_items(validator)
102
102
  (validator.attributes & attribute_names).present? &&
103
- (validator_items.is_a?(Proc) || validator_items.include?(nil))
103
+ (dynamic_validator_items?(validator_items) || validator_items.include?(nil))
104
104
 
105
105
  end
106
106
  end
@@ -172,6 +172,12 @@ module ActiveRecordDoctor
172
172
  validator.options[:in] || validator.options[:within] || []
173
173
  end
174
174
 
175
+ # The allowed values can be a Proc or a method name (Symbol) that's resolved
176
+ # at validation time, so the set of values isn't known statically.
177
+ def dynamic_validator_items?(validator_items)
178
+ validator_items.is_a?(Proc) || validator_items.is_a?(Symbol)
179
+ end
180
+
175
181
  # Determines whether the given column is used as a counter cache column by
176
182
  # a has_many association on the model.
177
183
  def counter_cache_column?(model, column)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record_doctor/detectors/base"
4
+
5
+ module ActiveRecordDoctor
6
+ module Detectors
7
+ class UnusedTables < Base # :nodoc:
8
+ @description = "detect tables not referenced by any model"
9
+ @config = {
10
+ ignore_tables: {
11
+ description: "tables whose corresponding models should not be checked for existence",
12
+ global: true
13
+ }
14
+ }
15
+
16
+ private
17
+
18
+ def message(table:)
19
+ "The #{table} table is not referenced by any Rails model and can be dropped"
20
+ end
21
+
22
+ def detect
23
+ each_table(except: config(:ignore_tables)) do |table|
24
+ next if models.any? { |model| model.table_name == table }
25
+
26
+ problem!(table: table)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordDoctor
4
- VERSION = "2.0.1"
4
+ VERSION = "2.1.0"
5
5
  end
@@ -22,6 +22,7 @@ require "active_record_doctor/detectors/short_primary_key_type"
22
22
  require "active_record_doctor/detectors/mismatched_foreign_key_type"
23
23
  require "active_record_doctor/detectors/table_without_primary_key"
24
24
  require "active_record_doctor/detectors/table_without_timestamps"
25
+ require "active_record_doctor/detectors/unused_tables"
25
26
  require "active_record_doctor/errors"
26
27
  require "active_record_doctor/help"
27
28
  require "active_record_doctor/runner"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_doctor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Navis
@@ -23,20 +23,48 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 7.0.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: minitest
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '5.0'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: minitest-fork_executor
28
42
  requirement: !ruby/object:Gem::Requirement
29
43
  requirements:
30
44
  - - "~>"
31
45
  - !ruby/object:Gem::Version
32
- version: 1.0.2
46
+ version: '1.1'
33
47
  type: :development
34
48
  prerelease: false
35
49
  version_requirements: !ruby/object:Gem::Requirement
36
50
  requirements:
37
51
  - - "~>"
38
52
  - !ruby/object:Gem::Version
39
- version: 1.0.2
53
+ version: '1.1'
54
+ - !ruby/object:Gem::Dependency
55
+ name: minitest-mock
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '5.27'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '5.27'
40
68
  - !ruby/object:Gem::Dependency
41
69
  name: mysql2
42
70
  requirement: !ruby/object:Gem::Requirement
@@ -111,16 +139,16 @@ dependencies:
111
139
  name: sqlite3
112
140
  requirement: !ruby/object:Gem::Requirement
113
141
  requirements:
114
- - - "~>"
142
+ - - ">="
115
143
  - !ruby/object:Gem::Version
116
- version: 2.2.0
144
+ version: '1.4'
117
145
  type: :development
118
146
  prerelease: false
119
147
  version_requirements: !ruby/object:Gem::Requirement
120
148
  requirements:
121
- - - "~>"
149
+ - - ">="
122
150
  - !ruby/object:Gem::Version
123
- version: 2.2.0
151
+ version: '1.4'
124
152
  - !ruby/object:Gem::Dependency
125
153
  name: transient_record
126
154
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +192,7 @@ files:
164
192
  - lib/active_record_doctor/detectors/undefined_table_references.rb
165
193
  - lib/active_record_doctor/detectors/unindexed_deleted_at.rb
166
194
  - lib/active_record_doctor/detectors/unindexed_foreign_keys.rb
195
+ - lib/active_record_doctor/detectors/unused_tables.rb
167
196
  - lib/active_record_doctor/errors.rb
168
197
  - lib/active_record_doctor/help.rb
169
198
  - lib/active_record_doctor/logger.rb
@@ -197,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
226
  - !ruby/object:Gem::Version
198
227
  version: '0'
199
228
  requirements: []
200
- rubygems_version: 3.6.7
229
+ rubygems_version: 4.0.20
201
230
  specification_version: 4
202
231
  summary: Identify database issues before they hit production.
203
232
  test_files: []