database_consistency 1.3.5 → 1.3.7

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/database_consistency/checkers/association_checkers/foreign_key_checker.rb +22 -22
  3. data/lib/database_consistency/checkers/association_checkers/foreign_key_type_checker.rb +10 -16
  4. data/lib/database_consistency/checkers/association_checkers/missing_index_checker.rb +5 -9
  5. data/lib/database_consistency/checkers/column_checkers/null_constraint_checker.rb +16 -16
  6. data/lib/database_consistency/checkers/column_checkers/primary_key_type_checker.rb +20 -20
  7. data/lib/database_consistency/checkers/index_checkers/redundant_index_checker.rb +18 -18
  8. data/lib/database_consistency/checkers/index_checkers/redundant_unique_index_checker.rb +18 -18
  9. data/lib/database_consistency/checkers/validator_checkers/missing_unique_index_checker.rb +18 -18
  10. data/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb +16 -9
  11. data/lib/database_consistency/report.rb +9 -12
  12. data/lib/database_consistency/report_builder.rb +24 -0
  13. data/lib/database_consistency/version.rb +1 -1
  14. data/lib/database_consistency/writers/autofix_writer.rb +2 -2
  15. data/lib/database_consistency/writers/simple/association_missing_index.rb +22 -0
  16. data/lib/database_consistency/writers/simple/association_missing_null_constraint.rb +22 -0
  17. data/lib/database_consistency/writers/simple/base.rb +9 -1
  18. data/lib/database_consistency/writers/simple/{error_message.rb → default_message.rb} +5 -1
  19. data/lib/database_consistency/writers/simple/has_one_missing_unique_index.rb +23 -0
  20. data/lib/database_consistency/writers/simple/inconsistent_types.rb +10 -1
  21. data/lib/database_consistency/writers/simple/length_validator_greater_limit.rb +22 -0
  22. data/lib/database_consistency/writers/simple/length_validator_lower_limit.rb +22 -0
  23. data/lib/database_consistency/writers/simple/length_validator_missing.rb +22 -0
  24. data/lib/database_consistency/writers/simple/missing_foreign_key.rb +24 -0
  25. data/lib/database_consistency/writers/simple/missing_unique_index.rb +23 -0
  26. data/lib/database_consistency/writers/simple/missing_uniqueness_validation.rb +22 -0
  27. data/lib/database_consistency/writers/simple/null_constraint_association_misses_validator.rb +7 -0
  28. data/lib/database_consistency/writers/simple/null_constraint_misses_validator.rb +22 -0
  29. data/lib/database_consistency/writers/simple/null_constraint_missing.rb +22 -0
  30. data/lib/database_consistency/writers/simple/possible_null.rb +22 -0
  31. data/lib/database_consistency/writers/simple/redundant_index.rb +6 -0
  32. data/lib/database_consistency/writers/simple/redundant_unique_index.rb +6 -0
  33. data/lib/database_consistency/writers/simple/small_primary_key.rb +22 -0
  34. data/lib/database_consistency/writers/simple_writer.rb +28 -22
  35. data/lib/database_consistency.rb +15 -1
  36. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f935ca51faca06dad689d217e897a035253f4ce9884f1826befdf1bcbbee3b5
4
- data.tar.gz: 38bde32ffee8b05b04bc8a1af261764f967b64f322352ef8d79729f1de485e13
3
+ metadata.gz: 3977b5e14b960051dad79361a32e435e511707612a269512fd42dcbac389216f
4
+ data.tar.gz: 95aba2661c7724aca4cee0e386b8f5e12e59f62b6444f35c66ebcabba2a6f9be
5
5
  SHA512:
6
- metadata.gz: 2352fa358c91e6dbec9a22c9abac34fb27b45e662c1402e88cfe94864b7bfa4966628f246a6f6f5d6c6af323e1320a3fe03c74df644f86ec6d14e4bde7c81962
7
- data.tar.gz: ad812a3ce4c8d4d0a7d24d9031815a26ae2c32bfca6d0721430f3c31f01d8c5910f4af091fb7d088e4860d65d887ba0a27531bdd0d8aefc50b589a944ef29290
6
+ metadata.gz: d71ae7f118719222bfcdb11329d8f0be6ca5c62d8f54ca145cd08f26d982e7e7b0a1b848397b19aa4e4a4c35e88602be24fd384896ed58cf6221f83e7d87280c
7
+ data.tar.gz: 0b1efa4b1c268d3959eae583bd4b2e3dc6da2585ac64a6ebf4b4a83ad73710f1a0c704ff1fdee4e13c01b5170c41bf593f31bd77a7f6bea9b6d417fe892208d6
@@ -4,17 +4,13 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks if non polymorphic +belongs_to+ association has foreign key constraint
6
6
  class ForeignKeyChecker < AssociationChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :primary_table, :primary_key, :foreign_table, :foreign_key
9
-
10
- def initialize(primary_table:, foreign_table:, primary_key:, foreign_key:, **args)
11
- super(**args)
12
- @primary_table = primary_table
13
- @primary_key = primary_key
14
- @foreign_table = foreign_table
15
- @foreign_key = foreign_key
16
- end
17
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :primary_table,
10
+ :primary_key,
11
+ :foreign_table,
12
+ :foreign_key
13
+ )
18
14
 
19
15
  private
20
16
 
@@ -43,22 +39,26 @@ module DatabaseConsistency
43
39
  # | ----------- | ------ |
44
40
  # | persisted | ok |
45
41
  # | missing | fail |
46
- def check # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
42
+ def check
47
43
  if model.connection.foreign_keys(model.table_name).find { |fk| fk.column == association.foreign_key.to_s }
48
44
  report_template(:ok)
49
45
  else
50
- Report.new(
51
- status: :fail,
52
- error_message: nil,
53
- error_slug: :missing_foreign_key,
54
- primary_table: association.table_name.to_s,
55
- primary_key: association.association_primary_key.to_s,
56
- foreign_table: association.active_record.table_name.to_s,
57
- foreign_key: association.foreign_key.to_s,
58
- **report_attributes
59
- )
46
+ report_template(:fail, error_slug: :missing_foreign_key)
60
47
  end
61
48
  end
49
+
50
+ def report_template(status, error_slug: nil)
51
+ Report.new(
52
+ status: status,
53
+ error_message: nil,
54
+ error_slug: error_slug,
55
+ primary_table: association.table_name.to_s,
56
+ primary_key: association.association_primary_key.to_s,
57
+ foreign_table: association.active_record.table_name.to_s,
58
+ foreign_key: association.foreign_key.to_s,
59
+ **report_attributes
60
+ )
61
+ end
62
62
  end
63
63
  end
64
64
  end
@@ -4,21 +4,15 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks if association's foreign key type covers associated model's primary key (same or bigger)
6
6
  class ForeignKeyTypeChecker < AssociationChecker
7
- ALLOWED_TYPES =
8
-
9
- class Report < DatabaseConsistency::Report # :nodoc:
10
- attr_reader :pk_name, :pk_type, :fk_name, :fk_type, :table_to_change, :type_to_set
11
-
12
- def initialize(fk_name: nil, fk_type: nil, pk_name: nil, pk_type: nil, table_to_change: nil, type_to_set: nil, **args) # rubocop:disable Metrics/ParameterLists, Layout/LineLength
13
- super(**args)
14
- @table_to_change = table_to_change
15
- @type_to_set = type_to_set
16
- @fk_name = fk_name
17
- @fk_type = fk_type
18
- @pk_name = pk_name
19
- @pk_type = pk_type
20
- end
21
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :pk_name,
10
+ :pk_type,
11
+ :fk_name,
12
+ :fk_type,
13
+ :table_to_change,
14
+ :type_to_set
15
+ )
22
16
 
23
17
  private
24
18
 
@@ -50,7 +44,7 @@ module DatabaseConsistency
50
44
  report_template(:fail, error_slug: :inconsistent_types)
51
45
  end
52
46
  rescue Errors::MissingField => e
53
- Report.new(
47
+ DatabaseConsistency::Report.new(
54
48
  status: :fail,
55
49
  error_slug: nil,
56
50
  error_message: e.message,
@@ -4,15 +4,11 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks if association's foreign key has index in the database
6
6
  class MissingIndexChecker < AssociationChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :table_name, :columns
9
-
10
- def initialize(table_name:, columns:, **args)
11
- super(**args)
12
- @table_name = table_name
13
- @columns = columns
14
- end
15
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :table_name,
10
+ :columns
11
+ )
16
12
 
17
13
  private
18
14
 
@@ -4,14 +4,10 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks missing presence validator
6
6
  class NullConstraintChecker < ColumnChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :association_name
9
-
10
- def initialize(association_name:, **args)
11
- super(**args)
12
- @association_name = association_name
13
- end
14
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :association_name
10
+ )
15
11
 
16
12
  private
17
13
 
@@ -33,22 +29,26 @@ module DatabaseConsistency
33
29
  #
34
30
  # We consider PresenceValidation, InclusionValidation, ExclusionValidation, NumericalityValidator with nil,
35
31
  # or required BelongsTo association using this column
36
- def check # rubocop:disable Metrics/MethodLength
32
+ def check
37
33
  if valid?
38
34
  report_template(:ok)
39
35
  elsif belongs_to_association
40
- Report.new(
41
- status: :fail,
42
- error_slug: :null_constraint_association_misses_validator,
43
- error_message: nil,
44
- association_name: belongs_to_association.name.to_s,
45
- **report_attributes
46
- )
36
+ report_template(:fail, error_slug: :null_constraint_association_misses_validator)
47
37
  else
48
38
  report_template(:fail, error_slug: :null_constraint_misses_validator)
49
39
  end
50
40
  end
51
41
 
42
+ def report_template(status, error_slug: nil)
43
+ Report.new(
44
+ status: status,
45
+ error_slug: error_slug,
46
+ error_message: nil,
47
+ association_name: belongs_to_association&.name&.to_s,
48
+ **report_attributes
49
+ )
50
+ end
51
+
52
52
  def valid?
53
53
  validator?(:presence, column.name) ||
54
54
  validator?(:inclusion, column.name) ||
@@ -4,16 +4,12 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks missing presence validator
6
6
  class PrimaryKeyTypeChecker < ColumnChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :fk_name, :table_to_change, :type_to_set
9
-
10
- def initialize(fk_name: nil, table_to_change: nil, type_to_set: nil, **args)
11
- super(**args)
12
- @table_to_change = table_to_change
13
- @type_to_set = type_to_set
14
- @fk_name = fk_name
15
- end
16
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :fk_name,
10
+ :table_to_change,
11
+ :type_to_set
12
+ )
17
13
 
18
14
  private
19
15
 
@@ -36,22 +32,26 @@ module DatabaseConsistency
36
32
  # | --------------------- | ------ |
37
33
  # | yes | ok |
38
34
  # | no | fail |
39
- def check # rubocop:disable Metrics/MethodLength
35
+ def check
40
36
  if valid?
41
37
  report_template(:ok)
42
38
  else
43
- Report.new(
44
- status: :fail,
45
- error_slug: :small_primary_key,
46
- error_message: nil,
47
- table_to_change: model.table_name,
48
- fk_name: column.name,
49
- type_to_set: type_to_set,
50
- **report_attributes
51
- )
39
+ report_template(:fail, error_slug: :small_primary_key)
52
40
  end
53
41
  end
54
42
 
43
+ def report_template(status, error_slug: nil)
44
+ Report.new(
45
+ status: status,
46
+ error_slug: error_slug,
47
+ error_message: nil,
48
+ table_to_change: model.table_name,
49
+ fk_name: column.name,
50
+ type_to_set: type_to_set,
51
+ **report_attributes
52
+ )
53
+ end
54
+
55
55
  def type_to_set
56
56
  VALID_TYPES_MAP[column.sql_type.to_s] || 'bigserial'
57
57
  end
@@ -4,15 +4,11 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks redundant database indexes
6
6
  class RedundantIndexChecker < IndexChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :covered_index_name, :index_name
9
-
10
- def initialize(covered_index_name:, index_name:, **args)
11
- super(**args)
12
- @covered_index_name = covered_index_name
13
- @index_name = index_name
14
- end
15
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :covered_index_name,
10
+ :index_name
11
+ )
16
12
 
17
13
  private
18
14
 
@@ -28,21 +24,25 @@ module DatabaseConsistency
28
24
  # | provided | ok |
29
25
  # | redundant | fail |
30
26
  #
31
- def check # rubocop:disable Metrics/MethodLength
27
+ def check
32
28
  if covered_by_index
33
- Report.new(
34
- status: :fail,
35
- error_slug: :redundant_index,
36
- error_message: nil,
37
- covered_index_name: covered_by_index.name,
38
- index_name: index.name,
39
- **report_attributes
40
- )
29
+ report_template(:fail, error_slug: :redundant_index)
41
30
  else
42
31
  report_template(:ok)
43
32
  end
44
33
  end
45
34
 
35
+ def report_template(status, error_slug: nil)
36
+ Report.new(
37
+ status: status,
38
+ error_slug: error_slug,
39
+ error_message: nil,
40
+ covered_index_name: covered_by_index&.name,
41
+ index_name: index.name,
42
+ **report_attributes
43
+ )
44
+ end
45
+
46
46
  def covered_by_index
47
47
  @covered_by_index ||=
48
48
  model.connection.indexes(model.table_name).find do |another_index|
@@ -4,15 +4,11 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks redundant database indexes
6
6
  class RedundantUniqueIndexChecker < IndexChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :index_name, :covered_index_name
9
-
10
- def initialize(covered_index_name:, index_name:, **args)
11
- super(**args)
12
- @index_name = index_name
13
- @covered_index_name = covered_index_name
14
- end
15
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :index_name,
10
+ :covered_index_name
11
+ )
16
12
 
17
13
  private
18
14
 
@@ -28,21 +24,25 @@ module DatabaseConsistency
28
24
  # | provided | ok |
29
25
  # | redundant | fail |
30
26
  #
31
- def check # rubocop:disable Metrics/MethodLength
27
+ def check
32
28
  if covered_by_index
33
- Report.new(
34
- status: :fail,
35
- error_slug: :redundant_unique_index,
36
- error_message: nil,
37
- index_name: index.name,
38
- covered_index_name: covered_by_index.name,
39
- **report_attributes
40
- )
29
+ report_template(:fail, error_slug: :redundant_unique_index)
41
30
  else
42
31
  report_template(:ok)
43
32
  end
44
33
  end
45
34
 
35
+ def report_template(status, error_slug: nil)
36
+ Report.new(
37
+ status: status,
38
+ error_slug: error_slug,
39
+ error_message: nil,
40
+ index_name: index.name,
41
+ covered_index_name: covered_by_index&.name,
42
+ **report_attributes
43
+ )
44
+ end
45
+
46
46
  def covered_by_index
47
47
  @covered_by_index ||=
48
48
  model.connection.indexes(model.table_name).find do |another_index|
@@ -4,15 +4,11 @@ module DatabaseConsistency
4
4
  module Checkers
5
5
  # This class checks if uniqueness validator has unique index in the database
6
6
  class MissingUniqueIndexChecker < ValidatorChecker
7
- class Report < DatabaseConsistency::Report # :nodoc:
8
- attr_reader :table_name, :columns
9
-
10
- def initialize(table_name:, columns:, **args)
11
- super(**args)
12
- @table_name = table_name
13
- @columns = columns
14
- end
15
- end
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :table_name,
10
+ :columns
11
+ )
16
12
 
17
13
  def column_or_attribute_name
18
14
  @column_or_attribute_name ||= Helper.uniqueness_validator_columns(attribute, validator, model).join('+')
@@ -31,21 +27,25 @@ module DatabaseConsistency
31
27
  # | ------------ | ------ |
32
28
  # | persisted | ok |
33
29
  # | missing | fail |
34
- def check # rubocop:disable Metrics/MethodLength
30
+ def check
35
31
  if unique_index
36
32
  report_template(:ok)
37
33
  else
38
- Report.new(
39
- status: :fail,
40
- error_slug: :missing_unique_index,
41
- error_message: nil,
42
- table_name: model.table_name,
43
- columns: sorted_uniqueness_validator_columns,
44
- **report_attributes
45
- )
34
+ report_template(:fail, error_slug: :missing_unique_index)
46
35
  end
47
36
  end
48
37
 
38
+ def report_template(status, error_slug: nil)
39
+ Report.new(
40
+ status: status,
41
+ error_slug: error_slug,
42
+ error_message: nil,
43
+ table_name: model.table_name,
44
+ columns: sorted_uniqueness_validator_columns,
45
+ **report_attributes
46
+ )
47
+ end
48
+
49
49
  def unique_index
50
50
  @unique_index ||= model.connection.indexes(model.table_name).find do |index|
51
51
  index.unique && Helper.extract_index_columns(index.columns).sort == sorted_uniqueness_validator_columns
@@ -6,15 +6,11 @@ module DatabaseConsistency
6
6
  class ColumnPresenceChecker < ValidatorsFractionChecker
7
7
  WEAK_OPTIONS = %i[allow_nil allow_blank if unless on].freeze
8
8
 
9
- class Report < DatabaseConsistency::Report # :nodoc:
10
- attr_reader :table_name, :column_name
11
-
12
- def initialize(table_name:, column_name:, **args)
13
- super(**args)
14
- @table_name = table_name
15
- @column_name = column_name
16
- end
17
- end
9
+ Report = ReportBuilder.define(
10
+ DatabaseConsistency::Report,
11
+ :table_name,
12
+ :column_name
13
+ )
18
14
 
19
15
  private
20
16
 
@@ -44,6 +40,17 @@ module DatabaseConsistency
44
40
  report_template(:fail, error_message: e.message)
45
41
  end
46
42
 
43
+ def report_template(status, error_message: nil, error_slug: nil)
44
+ Report.new(
45
+ status: status,
46
+ error_slug: error_slug,
47
+ error_message: error_message,
48
+ table_name: model.table_name.to_s,
49
+ column_name: attribute.to_s,
50
+ **report_attributes
51
+ )
52
+ end
53
+
47
54
  def weak_option?
48
55
  validators.all? { |validator| validator.options.slice(*WEAK_OPTIONS).any? }
49
56
  end
@@ -1,16 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatabaseConsistency
4
- class Report # :nodoc:
5
- attr_reader :checker_name, :table_or_model_name, :column_or_attribute_name, :status, :error_slug, :error_message
6
-
7
- def initialize(checker_name:, table_or_model_name:, column_or_attribute_name:, status:, error_slug:, error_message:) # rubocop:disable Metrics/ParameterLists
8
- @checker_name = checker_name
9
- @table_or_model_name = table_or_model_name
10
- @column_or_attribute_name = column_or_attribute_name
11
- @status = status
12
- @error_slug = error_slug
13
- @error_message = error_message
14
- end
15
- end
4
+ Report = ReportBuilder.define(
5
+ Class.new,
6
+ :checker_name,
7
+ :table_or_model_name,
8
+ :column_or_attribute_name,
9
+ :status,
10
+ :error_slug,
11
+ :error_message
12
+ )
16
13
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ class ReportBuilder # :nodoc:
5
+ def self.define(klass, *attrs) # rubocop:disable Metrics/MethodLength
6
+ Class.new(klass) do
7
+ attr_reader(*attrs)
8
+
9
+ class_eval(<<~DEF, __FILE__, __LINE__ + 1)
10
+ def initialize(#{attrs.map { |attr| "#{attr}:" }.join(', ')}, **opts)
11
+ super(**opts) if opts.any?
12
+ #{attrs.map { |attr| "@#{attr} = #{attr}" }.join("\n")}
13
+ end
14
+
15
+ def to_h
16
+ h = defined?(super) ? super : {}
17
+ #{attrs.map { |attr| "h[#{attr}] = #{attr}" }.join("\n")}
18
+ h
19
+ end
20
+ DEF
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatabaseConsistency
4
- VERSION = '1.3.5'
4
+ VERSION = '1.3.7'
5
5
  end
@@ -41,8 +41,8 @@ module DatabaseConsistency
41
41
  klass&.new(report)
42
42
  end
43
43
 
44
- def unique_key(report)
45
- [report.class, report.attributes]
44
+ def unique_key(generator)
45
+ [generator.class, generator.attributes]
46
46
  end
47
47
  end
48
48
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class AssociationMissingIndex < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'associated model should have proper index in the database'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_name: report.table_name,
16
+ columns: report.columns
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class AssociationMissingNullConstraint < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'association foreign key column should be required in the database'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_name: report.table_name,
16
+ column_name: report.column_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -33,11 +33,19 @@ module DatabaseConsistency
33
33
  end
34
34
 
35
35
  def msg
36
- "#{report.checker_name} #{status_text} #{key_text} #{message_text}"
36
+ "#{report.checker_name} #{status_text} #{key_text} #{message_text}".strip
37
+ end
38
+
39
+ def unique_key
40
+ { class: self.class }.merge(unique_attributes)
37
41
  end
38
42
 
39
43
  private
40
44
 
45
+ def unique_attributes
46
+ raise StandardError, 'Missing the implementation'
47
+ end
48
+
41
49
  def message_text
42
50
  template % attributes
43
51
  end
@@ -3,12 +3,16 @@
3
3
  module DatabaseConsistency
4
4
  module Writers
5
5
  module Simple
6
- class ErrorMessage < Base # :nodoc:
6
+ class DefaultMessage < Base # :nodoc:
7
7
  private
8
8
 
9
9
  def template
10
10
  report.error_message || ''
11
11
  end
12
+
13
+ def unique_attributes
14
+ report.to_h
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class HasOneMissingUniqueIndex < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'associated model should have proper unique index in the database'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_name: report.table_name,
16
+ columns: report.columns,
17
+ unique: true
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,7 +7,8 @@ module DatabaseConsistency
7
7
  private
8
8
 
9
9
  def template
10
- "foreign key %<fk_name>s with type %<fk_type>s doesn't cover primary key %<pk_name>s with type %<pk_type>s"
10
+ "foreign key (%<fk_name>s) with type (%<fk_type>s) doesn't "\
11
+ 'cover primary key (%<pk_name>s) with type (%<pk_type>s)'
11
12
  end
12
13
 
13
14
  def attributes
@@ -18,6 +19,14 @@ module DatabaseConsistency
18
19
  pk_type: report.pk_type
19
20
  }
20
21
  end
22
+
23
+ def unique_attributes
24
+ {
25
+ table_to_change: report.table_to_change,
26
+ type_to_set: report.type_to_set,
27
+ fk_name: report.fk_name
28
+ }
29
+ end
21
30
  end
22
31
  end
23
32
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class LengthValidatorGreaterLimit < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column has greater limit in the database than in length validator'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class LengthValidatorLowerLimit < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column has lower limit in the database than in length validator'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class LengthValidatorMissing < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column has limit in the database but do not have length validator'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class MissingForeignKey < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'should have foreign key in the database'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ foreign_table: report.foreign_table,
16
+ foreign_key: report.foreign_key,
17
+ primary_table: report.primary_table,
18
+ primary_key: report.primary_key
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class MissingUniqueIndex < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'model should have proper unique index in the database'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_name: report.table_name,
16
+ columns: report.columns,
17
+ unique: true
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class MissingUniquenessValidation < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'index is unique in the database but do not have uniqueness validator'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -15,6 +15,13 @@ module DatabaseConsistency
15
15
  association_name: report.association_name
16
16
  }
17
17
  end
18
+
19
+ def unique_attributes
20
+ {
21
+ table_or_model_name: report.table_or_model_name,
22
+ column_or_attribute_name: report.column_or_attribute_name
23
+ }
24
+ end
18
25
  end
19
26
  end
20
27
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class NullConstraintMissesValidator < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column is required in the database but do not have presence validator'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class NullConstraintMissing < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column should be required in the database'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_name: report.table_name,
16
+ column_name: report.column_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class PossibleNull < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column is required but there is possible null value insert'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -15,6 +15,12 @@ module DatabaseConsistency
15
15
  covered_index_name: report.covered_index_name
16
16
  }
17
17
  end
18
+
19
+ def unique_attributes
20
+ {
21
+ index_name: report.index_name
22
+ }
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -15,6 +15,12 @@ module DatabaseConsistency
15
15
  covered_index_name: report.covered_index_name
16
16
  }
17
17
  end
18
+
19
+ def unique_attributes
20
+ {
21
+ index_name: report.index_name
22
+ }
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class SmallPrimaryKey < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'column has int/serial type but recommended to have bigint/bigserial/uuid'
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ table_or_model_name: report.table_or_model_name,
16
+ column_or_attribute_name: report.column_or_attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -6,43 +6,49 @@ module DatabaseConsistency
6
6
  # The simplest formatter
7
7
  class SimpleWriter < BaseWriter
8
8
  SLUG_TO_WRITER = {
9
- association_missing_index: Simple::Base.with('associated model should have proper index in the database'),
10
- association_missing_null_constraint: Simple::Base.with('association foreign key column should be required in the database'), # rubocop:disable Layout/LineLength
11
- has_one_missing_unique_index: Simple::Base.with('associated model should have proper unique index in the database'), # rubocop:disable Layout/LineLength
9
+ association_missing_index: Simple::AssociationMissingIndex,
10
+ association_missing_null_constraint: Simple::AssociationMissingNullConstraint,
11
+ has_one_missing_unique_index: Simple::HasOneMissingUniqueIndex,
12
12
  inconsistent_types: Simple::InconsistentTypes,
13
- length_validator_greater_limit: Simple::Base.with('column has greater limit in the database than in length validator'), # rubocop:disable Layout/LineLength
14
- length_validator_lower_limit: Simple::Base.with('column has lower limit in the database than in length validator'), # rubocop:disable Layout/LineLength
15
- length_validator_missing: Simple::Base.with('column has limit in the database but do not have length validator'), # rubocop:disable Layout/LineLength
16
- missing_foreign_key: Simple::Base.with('should have foreign key in the database'),
17
- missing_unique_index: Simple::Base.with('model should have proper unique index in the database'),
18
- missing_uniqueness_validation: Simple::Base.with('index is unique in the database but do not have uniqueness validator'), # rubocop:disable Layout/LineLength
13
+ length_validator_greater_limit: Simple::LengthValidatorGreaterLimit,
14
+ length_validator_lower_limit: Simple::LengthValidatorLowerLimit,
15
+ length_validator_missing: Simple::LengthValidatorMissing,
16
+ missing_foreign_key: Simple::MissingForeignKey,
17
+ missing_unique_index: Simple::MissingUniqueIndex,
18
+ missing_uniqueness_validation: Simple::MissingUniquenessValidation,
19
19
  null_constraint_association_misses_validator: Simple::NullConstraintAssociationMissesValidator,
20
- null_constraint_misses_validator: Simple::Base.with('column is required in the database but do not have presence validator'), # rubocop:disable Layout/LineLength
21
- null_constraint_missing: Simple::Base.with('column should be required in the database'),
22
- possible_null: Simple::Base.with('column is required but there is possible null value insert'),
20
+ null_constraint_misses_validator: Simple::NullConstraintMissesValidator,
21
+ null_constraint_missing: Simple::NullConstraintMissing,
22
+ possible_null: Simple::PossibleNull,
23
23
  redundant_index: Simple::RedundantIndex,
24
24
  redundant_unique_index: Simple::RedundantUniqueIndex,
25
- small_primary_key: Simple::Base.with('column has int/serial type but recommended to have bigint/bigserial/uuid')
25
+ small_primary_key: Simple::SmallPrimaryKey
26
26
  }.freeze
27
27
 
28
28
  def write
29
- results.each do |result|
30
- next unless write?(result.status)
31
-
32
- writer = writer(result)
33
-
34
- puts writer.msg
29
+ results.select(&method(:write?))
30
+ .map(&method(:writer))
31
+ .group_by(&:unique_key)
32
+ .each_value do |writers|
33
+ puts message(writers)
35
34
  end
36
35
  end
37
36
 
38
37
  private
39
38
 
40
- def write?(status)
41
- status == :fail || config.debug?
39
+ def message(writers)
40
+ msg = writers.first.msg
41
+ return msg if writers.size == 1
42
+
43
+ "#{msg}. Total grouped offenses: #{writers.size}"
44
+ end
45
+
46
+ def write?(report)
47
+ report.status == :fail || config.debug?
42
48
  end
43
49
 
44
50
  def writer(report)
45
- klass = SLUG_TO_WRITER[report.error_slug] || Simple::ErrorMessage
51
+ klass = SLUG_TO_WRITER[report.error_slug] || Simple::DefaultMessage
46
52
  klass.new(report, config: config)
47
53
  end
48
54
  end
@@ -7,17 +7,31 @@ require 'database_consistency/helper'
7
7
  require 'database_consistency/configuration'
8
8
  require 'database_consistency/rescue_error'
9
9
  require 'database_consistency/errors'
10
+ require 'database_consistency/report_builder'
10
11
  require 'database_consistency/report'
11
12
 
12
13
  require 'database_consistency/writers/base_writer'
13
14
  require 'database_consistency/writers/todo_writer'
14
15
 
15
16
  require 'database_consistency/writers/simple/base'
16
- require 'database_consistency/writers/simple/error_message'
17
+ require 'database_consistency/writers/simple/default_message'
17
18
  require 'database_consistency/writers/simple/inconsistent_types'
18
19
  require 'database_consistency/writers/simple/null_constraint_association_misses_validator'
19
20
  require 'database_consistency/writers/simple/redundant_index'
20
21
  require 'database_consistency/writers/simple/redundant_unique_index'
22
+ require 'database_consistency/writers/simple/association_missing_index'
23
+ require 'database_consistency/writers/simple/association_missing_null_constraint'
24
+ require 'database_consistency/writers/simple/has_one_missing_unique_index'
25
+ require 'database_consistency/writers/simple/length_validator_lower_limit'
26
+ require 'database_consistency/writers/simple/length_validator_greater_limit'
27
+ require 'database_consistency/writers/simple/length_validator_missing'
28
+ require 'database_consistency/writers/simple/missing_foreign_key'
29
+ require 'database_consistency/writers/simple/missing_unique_index'
30
+ require 'database_consistency/writers/simple/missing_uniqueness_validation'
31
+ require 'database_consistency/writers/simple/null_constraint_misses_validator'
32
+ require 'database_consistency/writers/simple/null_constraint_missing'
33
+ require 'database_consistency/writers/simple/possible_null'
34
+ require 'database_consistency/writers/simple/small_primary_key'
21
35
  require 'database_consistency/writers/simple_writer'
22
36
 
23
37
  require 'database_consistency/writers/autofix/helpers/migration'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: database_consistency
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-13 00:00:00.000000000 Z
11
+ date: 2022-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -176,6 +176,7 @@ files:
176
176
  - lib/database_consistency/processors/validators_fractions_processor.rb
177
177
  - lib/database_consistency/processors/validators_processor.rb
178
178
  - lib/database_consistency/report.rb
179
+ - lib/database_consistency/report_builder.rb
179
180
  - lib/database_consistency/rescue_error.rb
180
181
  - lib/database_consistency/templates/rails_defaults.yml
181
182
  - lib/database_consistency/version.rb
@@ -196,12 +197,25 @@ files:
196
197
  - lib/database_consistency/writers/autofix/templates/redundant_index.tt
197
198
  - lib/database_consistency/writers/autofix_writer.rb
198
199
  - lib/database_consistency/writers/base_writer.rb
200
+ - lib/database_consistency/writers/simple/association_missing_index.rb
201
+ - lib/database_consistency/writers/simple/association_missing_null_constraint.rb
199
202
  - lib/database_consistency/writers/simple/base.rb
200
- - lib/database_consistency/writers/simple/error_message.rb
203
+ - lib/database_consistency/writers/simple/default_message.rb
204
+ - lib/database_consistency/writers/simple/has_one_missing_unique_index.rb
201
205
  - lib/database_consistency/writers/simple/inconsistent_types.rb
206
+ - lib/database_consistency/writers/simple/length_validator_greater_limit.rb
207
+ - lib/database_consistency/writers/simple/length_validator_lower_limit.rb
208
+ - lib/database_consistency/writers/simple/length_validator_missing.rb
209
+ - lib/database_consistency/writers/simple/missing_foreign_key.rb
210
+ - lib/database_consistency/writers/simple/missing_unique_index.rb
211
+ - lib/database_consistency/writers/simple/missing_uniqueness_validation.rb
202
212
  - lib/database_consistency/writers/simple/null_constraint_association_misses_validator.rb
213
+ - lib/database_consistency/writers/simple/null_constraint_misses_validator.rb
214
+ - lib/database_consistency/writers/simple/null_constraint_missing.rb
215
+ - lib/database_consistency/writers/simple/possible_null.rb
203
216
  - lib/database_consistency/writers/simple/redundant_index.rb
204
217
  - lib/database_consistency/writers/simple/redundant_unique_index.rb
218
+ - lib/database_consistency/writers/simple/small_primary_key.rb
205
219
  - lib/database_consistency/writers/simple_writer.rb
206
220
  - lib/database_consistency/writers/todo_writer.rb
207
221
  homepage: https://github.com/djezzzl/database_consistency