database_consistency 1.1.0 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
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