database_consistency 1.1.0 → 1.1.4

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: f37408420931f459ea476d095f441e40256ea2279e07c21ad9d477c0781d5944
4
- data.tar.gz: b054877a7819333fab57dbe22786456d4a0328b462f9808561e470290b3ae6e7
3
+ metadata.gz: 33bfe05b79b4c641cfa784c2e60894004910bfcbf594d3045ce51b586eec5812
4
+ data.tar.gz: 20355a79ba3aa941f85764203474e8a16b5c91397ce008940f4ecb9a2e45d71a
5
5
  SHA512:
6
- metadata.gz: c2e7a18dabde150f3f1f2ee144b6076e2c0fb944c9c128851379e86007f0aed056f1fb550cc19319b777767ffc165534939a680e248213473032054dfa8e2924
7
- data.tar.gz: f047ff2a3e5e41137a93f5c64e4a0288e74b0d687670e7eabe5b3656a675abf87df75586fd5a0988f25f26f993d20542addfd2d84b430dac7dd30025f2016415
6
+ metadata.gz: 57e588223f73d55f10d00e47c7492de68849f3487a272293beb8eba3547bea679f4c2322a93fc2ac625177426252ba1d97650197515493a17218face6149b493
7
+ data.tar.gz: d21a4eab903327f8fd7ea775828c45c72674f6edf58b1f8fb0889cd986a79adaf514a160bb30497b9b46003b180888b97ddfe94c25b68a106ed4e15a97d8d25b
@@ -2,18 +2,23 @@
2
2
 
3
3
  module DatabaseConsistency
4
4
  module Checkers
5
- # This class checks if required +belongs_to+ has foreign key constraint
6
- class BelongsToPresenceChecker < ValidatorChecker
7
- MISSING_FOREIGN_KEY = 'model should have proper foreign key in the database'
5
+ # This class checks if non polymorphic +belongs_to+ association has foreign key constraint
6
+ class ForeignKeyChecker < AssociationChecker
7
+ MISSING_FOREIGN_KEY = 'should have foreign key in the database'
8
8
 
9
9
  private
10
10
 
11
11
  # We skip check when:
12
- # - validator is a not a presence validator
13
- # - there is no belongs_to association with given name
14
- # - belongs_to association is polymorphic
12
+ # - association isn't belongs_to association
13
+ # - association is polymorphic
15
14
  def preconditions
16
- validator.kind == :presence && association && association.belongs_to? && !association.polymorphic?
15
+ supported? && association.belongs_to? && !association.polymorphic?
16
+ end
17
+
18
+ def supported?
19
+ return false if ActiveRecord::VERSION::MAJOR < 5 && ActiveRecord::Base.connection_config[:adapter] == 'sqlite3'
20
+
21
+ true
17
22
  end
18
23
 
19
24
  # Table of possible statuses
@@ -28,10 +33,6 @@ module DatabaseConsistency
28
33
  report_template(:fail, MISSING_FOREIGN_KEY)
29
34
  end
30
35
  end
31
-
32
- def association
33
- @association ||= model.reflect_on_association(attribute)
34
- end
35
36
  end
36
37
  end
37
38
  end
@@ -38,10 +38,14 @@ module DatabaseConsistency
38
38
  model.connection.indexes(model.table_name).find do |another_index|
39
39
  next if index.name == another_index.name
40
40
 
41
- include_index_as_prefix?(another_index)
41
+ clause_equals?(another_index) && include_index_as_prefix?(another_index)
42
42
  end
43
43
  end
44
44
 
45
+ def clause_equals?(another_index)
46
+ another_index.where == index.where
47
+ end
48
+
45
49
  def include_index_as_prefix?(another_index)
46
50
  another_index_columns = Helper.extract_index_columns(another_index.columns)
47
51
  index_columns == another_index_columns.first(index_columns.size)
@@ -38,10 +38,14 @@ module DatabaseConsistency
38
38
  model.connection.indexes(model.table_name).find do |another_index|
39
39
  next if index.name == another_index.name
40
40
 
41
- another_index.unique && contain_index?(another_index)
41
+ another_index.unique && clause_equals?(another_index) && contain_index?(another_index)
42
42
  end
43
43
  end
44
44
 
45
+ def clause_equals?(another_index)
46
+ another_index.where == index.where
47
+ end
48
+
45
49
  def contain_index?(another_index)
46
50
  another_index_columns = Helper.extract_index_columns(another_index.columns)
47
51
  index_columns & another_index_columns == another_index_columns
@@ -7,6 +7,7 @@ module DatabaseConsistency
7
7
  WEAK_OPTIONS = %i[allow_nil allow_blank if unless on].freeze
8
8
  # Message templates
9
9
  CONSTRAINT_MISSING = 'column should be required in the database'
10
+ ASSOCIATION_FOREIGN_KEY_CONSTRAINT_MISSING = 'association foreign key column should be required in the database'
10
11
  POSSIBLE_NULL = 'column is required but there is possible null value insert'
11
12
 
12
13
  private
@@ -15,11 +16,9 @@ module DatabaseConsistency
15
16
  validator.kind == :presence
16
17
  end
17
18
 
18
- # We skip check when:
19
- # - there is no presence validators
20
- # - there is no column in the database with given name
19
+ # We skip the check when there are no presence validators
21
20
  def preconditions
22
- validators.any? && column
21
+ validators.any?
23
22
  end
24
23
 
25
24
  # Table of possible statuses
@@ -33,17 +32,39 @@ module DatabaseConsistency
33
32
  can_be_null = column.null
34
33
  has_weak_option = validators.all? { |validator| validator.options.slice(*WEAK_OPTIONS).any? }
35
34
 
36
- if can_be_null == has_weak_option
37
- report_template(:ok)
38
- elsif can_be_null
35
+ return report_template(:ok) if can_be_null == has_weak_option
36
+ return report_template(:fail, POSSIBLE_NULL) unless can_be_null
37
+
38
+ if regular_column
39
39
  report_template(:fail, CONSTRAINT_MISSING)
40
40
  else
41
- report_template(:fail, POSSIBLE_NULL)
41
+ report_template(:fail, ASSOCIATION_FOREIGN_KEY_CONSTRAINT_MISSING)
42
42
  end
43
43
  end
44
44
 
45
45
  def column
46
- @column ||= model.columns.select.find { |field| field.name == attribute.to_s }
46
+ @column ||= regular_column || association_reference_column ||
47
+ (raise Errors::MissingField, "Missing column in #{model.table_name} for #{attribute}")
48
+ end
49
+
50
+ def regular_column
51
+ @regular_column ||= column_for_name(attribute.to_s)
52
+ end
53
+
54
+ def column_for_name(name)
55
+ model.columns.find { |field| field.name == name.to_s }
56
+ end
57
+
58
+ def association_reference_column
59
+ return unless association_reflection
60
+
61
+ column_for_name(association_reflection.foreign_key)
62
+ end
63
+
64
+ def association_reflection
65
+ model
66
+ .reflect_on_all_associations
67
+ .find { |reflection| reflection.belongs_to? && reflection.name == attribute }
47
68
  end
48
69
  end
49
70
  end
@@ -6,6 +6,7 @@ module DatabaseConsistency
6
6
  class AssociationsProcessor < BaseProcessor
7
7
  CHECKERS = [
8
8
  Checkers::MissingIndexChecker,
9
+ Checkers::ForeignKeyChecker,
9
10
  Checkers::ForeignKeyTypeChecker
10
11
  ].freeze
11
12
 
@@ -5,7 +5,6 @@ module DatabaseConsistency
5
5
  # The class to process validators
6
6
  class ValidatorsProcessor < BaseProcessor
7
7
  CHECKERS = [
8
- Checkers::BelongsToPresenceChecker,
9
8
  Checkers::MissingUniqueIndexChecker
10
9
  ].freeze
11
10
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatabaseConsistency
4
- VERSION = '1.1.0'
4
+ VERSION = '1.1.4'
5
5
  end
@@ -21,9 +21,7 @@ module DatabaseConsistency
21
21
  end
22
22
 
23
23
  def msg(result)
24
- msg = "#{status_text(result)} #{key_text(result)} #{result.message}"
25
- msg += " (checker: #{result.checker_name})" if config.debug?
26
- msg
24
+ "#{result.checker_name} #{status_text(result)} #{key_text(result)} #{result.message}"
27
25
  end
28
26
 
29
27
  private
@@ -19,6 +19,7 @@ require 'database_consistency/checkers/base_checker'
19
19
 
20
20
  require 'database_consistency/checkers/association_checkers/association_checker'
21
21
  require 'database_consistency/checkers/association_checkers/missing_index_checker'
22
+ require 'database_consistency/checkers/association_checkers/foreign_key_checker'
22
23
  require 'database_consistency/checkers/association_checkers/foreign_key_type_checker'
23
24
 
24
25
  require 'database_consistency/checkers/column_checkers/column_checker'
@@ -27,7 +28,6 @@ require 'database_consistency/checkers/column_checkers/length_constraint_checker
27
28
  require 'database_consistency/checkers/column_checkers/primary_key_type_checker'
28
29
 
29
30
  require 'database_consistency/checkers/validator_checkers/validator_checker'
30
- require 'database_consistency/checkers/validator_checkers/belongs_to_presence_checker'
31
31
  require 'database_consistency/checkers/validator_checkers/missing_unique_index_checker'
32
32
 
33
33
  require 'database_consistency/checkers/validators_fraction_checkers/validators_fraction_checker'
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.1.0
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-24 00:00:00.000000000 Z
11
+ date: 2021-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -133,6 +133,7 @@ files:
133
133
  - bin/database_consistency
134
134
  - lib/database_consistency.rb
135
135
  - lib/database_consistency/checkers/association_checkers/association_checker.rb
136
+ - lib/database_consistency/checkers/association_checkers/foreign_key_checker.rb
136
137
  - lib/database_consistency/checkers/association_checkers/foreign_key_type_checker.rb
137
138
  - lib/database_consistency/checkers/association_checkers/missing_index_checker.rb
138
139
  - lib/database_consistency/checkers/base_checker.rb
@@ -144,7 +145,6 @@ files:
144
145
  - lib/database_consistency/checkers/index_checkers/redundant_index_checker.rb
145
146
  - lib/database_consistency/checkers/index_checkers/redundant_unique_index_checker.rb
146
147
  - lib/database_consistency/checkers/index_checkers/unique_index_checker.rb
147
- - lib/database_consistency/checkers/validator_checkers/belongs_to_presence_checker.rb
148
148
  - lib/database_consistency/checkers/validator_checkers/missing_unique_index_checker.rb
149
149
  - lib/database_consistency/checkers/validator_checkers/validator_checker.rb
150
150
  - lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb