database_consistency 1.1.2 → 1.1.6
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 +4 -4
- data/lib/database_consistency/checkers/{validator_checkers/belongs_to_presence_checker.rb → association_checkers/foreign_key_checker.rb} +12 -11
- data/lib/database_consistency/checkers/association_checkers/foreign_key_type_checker.rb +4 -2
- data/lib/database_consistency/checkers/column_checkers/null_constraint_checker.rb +20 -14
- data/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb +41 -10
- data/lib/database_consistency/processors/associations_processor.rb +1 -0
- data/lib/database_consistency/processors/validators_processor.rb +0 -1
- data/lib/database_consistency/version.rb +1 -1
- data/lib/database_consistency.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 482d9a79d349bbe6d49233cf8ffb05accbf61c9d30db72b8e2d9c5d5517602a6
|
4
|
+
data.tar.gz: 14309f3ef7aab0e6aa0d20e4f9a0c0148a2be89e30d09235fb558cc55085d38d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7abe1d2b81e1f557b20da7c61a33c9fab8ebe709dd459e78ec16c4b088b3a457b094985428d72f882c6e946d028a444bfaf6aa1058764f03aef6bb54c2ecd89c
|
7
|
+
data.tar.gz: d2b930d6d7a0f639c9f7f139f207d90df85af5409d918d77cf7f3c781602844220996eb3fef6639f0c490f33235efa74f92817a254eb5ee4930ec429c4a4c02d
|
@@ -2,18 +2,23 @@
|
|
2
2
|
|
3
3
|
module DatabaseConsistency
|
4
4
|
module Checkers
|
5
|
-
# This class checks if
|
6
|
-
class
|
7
|
-
MISSING_FOREIGN_KEY = '
|
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
|
-
# -
|
13
|
-
# -
|
14
|
-
# - belongs_to association is polymorphic
|
12
|
+
# - association isn't belongs_to association
|
13
|
+
# - association is polymorphic
|
15
14
|
def preconditions
|
16
|
-
|
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
|
@@ -42,6 +42,8 @@ module DatabaseConsistency
|
|
42
42
|
else
|
43
43
|
report_template(:fail, render_text)
|
44
44
|
end
|
45
|
+
rescue Errors::MissingField => e
|
46
|
+
report_template(:fail, e.message)
|
45
47
|
end
|
46
48
|
|
47
49
|
# @return [String]
|
@@ -101,8 +103,8 @@ module DatabaseConsistency
|
|
101
103
|
|
102
104
|
# @return [String]
|
103
105
|
def missing_field_error(table_name, column_name)
|
104
|
-
"
|
105
|
-
"field (#{column_name}) of table (#{table_name}) but it is missing
|
106
|
+
"association (#{association.name}) of class (#{association.active_record}) relies on "\
|
107
|
+
"field (#{column_name}) of table (#{table_name}) but it is missing"
|
106
108
|
end
|
107
109
|
|
108
110
|
# @param [ActiveRecord::ConnectionAdapters::Column] column
|
@@ -6,6 +6,8 @@ module DatabaseConsistency
|
|
6
6
|
class NullConstraintChecker < ColumnChecker
|
7
7
|
# Message templates
|
8
8
|
VALIDATOR_MISSING = 'column is required in the database but do not have presence validator'
|
9
|
+
ASSOCIATION_VALIDATOR_MISSING = 'column is required in the database but do '\
|
10
|
+
'not have presence validator for association (%a_n)'
|
9
11
|
|
10
12
|
private
|
11
13
|
|
@@ -26,21 +28,23 @@ module DatabaseConsistency
|
|
26
28
|
# | missing | fail |
|
27
29
|
#
|
28
30
|
# We consider PresenceValidation, InclusionValidation, ExclusionValidation, NumericalityValidator with nil,
|
29
|
-
# or BelongsTo association using this column
|
31
|
+
# or required BelongsTo association using this column
|
30
32
|
def check
|
31
33
|
if valid?
|
32
34
|
report_template(:ok)
|
35
|
+
elsif belongs_to_association
|
36
|
+
report_template(:fail, ASSOCIATION_VALIDATOR_MISSING.gsub('%a_n', belongs_to_association.name.to_s))
|
33
37
|
else
|
34
38
|
report_template(:fail, VALIDATOR_MISSING)
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
38
42
|
def valid?
|
39
|
-
validator?(
|
40
|
-
validator?(
|
43
|
+
validator?(:presence, column.name) ||
|
44
|
+
validator?(:inclusion, column.name) ||
|
41
45
|
numericality_validator_without_allow_nil? ||
|
42
46
|
nil_exclusion_validator? ||
|
43
|
-
belongs_to_association?
|
47
|
+
(belongs_to_association && validator?(:presence, belongs_to_association.name))
|
44
48
|
end
|
45
49
|
|
46
50
|
def primary_field?
|
@@ -52,28 +56,30 @@ module DatabaseConsistency
|
|
52
56
|
end
|
53
57
|
|
54
58
|
def nil_exclusion_validator?
|
55
|
-
model.validators.
|
56
|
-
|
59
|
+
model.validators.any? do |validator|
|
60
|
+
validator.kind == :exclusion &&
|
61
|
+
Helper.check_inclusion?(validator.attributes, column.name) &&
|
57
62
|
validator.options[:in].include?(nil)
|
58
63
|
end
|
59
64
|
end
|
60
65
|
|
61
66
|
def numericality_validator_without_allow_nil?
|
62
|
-
model.validators.
|
63
|
-
|
67
|
+
model.validators.any? do |validator|
|
68
|
+
validator.kind == :numericality &&
|
69
|
+
Helper.check_inclusion?(validator.attributes, column.name) &&
|
64
70
|
!validator.options[:allow_nil]
|
65
71
|
end
|
66
72
|
end
|
67
73
|
|
68
|
-
def validator?(
|
69
|
-
model.validators.
|
70
|
-
Helper.check_inclusion?(validator.attributes,
|
74
|
+
def validator?(kind, attribute)
|
75
|
+
model.validators.any? do |validator|
|
76
|
+
validator.kind == kind && Helper.check_inclusion?(validator.attributes, attribute)
|
71
77
|
end
|
72
78
|
end
|
73
79
|
|
74
|
-
def belongs_to_association
|
75
|
-
model.reflect_on_all_associations.
|
76
|
-
Helper.check_inclusion?([r.foreign_key, r.foreign_type], column.name)
|
80
|
+
def belongs_to_association
|
81
|
+
@belongs_to_association ||= model.reflect_on_all_associations.find do |r|
|
82
|
+
r.belongs_to? && Helper.check_inclusion?([r.foreign_key, r.foreign_type], column.name)
|
77
83
|
end
|
78
84
|
end
|
79
85
|
end
|
data/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb
CHANGED
@@ -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?
|
21
|
+
validators.any?
|
23
22
|
end
|
24
23
|
|
25
24
|
# Table of possible statuses
|
@@ -30,20 +29,52 @@ module DatabaseConsistency
|
|
30
29
|
# | all missing | required | ok |
|
31
30
|
# | all missing | optional | fail |
|
32
31
|
def check
|
32
|
+
report_message
|
33
|
+
rescue Errors::MissingField => e
|
34
|
+
report_template(:fail, e.message)
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_weak_option?
|
38
|
+
validators.all? { |validator| validator.options.slice(*WEAK_OPTIONS).any? }
|
39
|
+
end
|
40
|
+
|
41
|
+
def report_message
|
33
42
|
can_be_null = column.null
|
34
|
-
has_weak_option =
|
43
|
+
has_weak_option = has_weak_option?
|
35
44
|
|
36
|
-
if can_be_null == has_weak_option
|
37
|
-
|
38
|
-
|
45
|
+
return report_template(:ok) if can_be_null == has_weak_option
|
46
|
+
return report_template(:fail, POSSIBLE_NULL) unless can_be_null
|
47
|
+
|
48
|
+
if regular_column
|
39
49
|
report_template(:fail, CONSTRAINT_MISSING)
|
40
50
|
else
|
41
|
-
report_template(:fail,
|
51
|
+
report_template(:fail, ASSOCIATION_FOREIGN_KEY_CONSTRAINT_MISSING)
|
42
52
|
end
|
43
53
|
end
|
44
54
|
|
45
55
|
def column
|
46
|
-
@column ||=
|
56
|
+
@column ||= regular_column || association_reference_column ||
|
57
|
+
(raise Errors::MissingField, "column (#{attribute}) is missing in table (#{model.table_name}) but used for presence validation")
|
58
|
+
end
|
59
|
+
|
60
|
+
def regular_column
|
61
|
+
@regular_column ||= column_for_name(attribute.to_s)
|
62
|
+
end
|
63
|
+
|
64
|
+
def column_for_name(name)
|
65
|
+
model.columns.find { |field| field.name == name.to_s }
|
66
|
+
end
|
67
|
+
|
68
|
+
def association_reference_column
|
69
|
+
return unless association_reflection
|
70
|
+
|
71
|
+
column_for_name(association_reflection.foreign_key)
|
72
|
+
end
|
73
|
+
|
74
|
+
def association_reflection
|
75
|
+
model
|
76
|
+
.reflect_on_all_associations
|
77
|
+
.find { |reflection| reflection.belongs_to? && reflection.name == attribute }
|
47
78
|
end
|
48
79
|
end
|
49
80
|
end
|
data/lib/database_consistency.rb
CHANGED
@@ -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.
|
4
|
+
version: 1.1.6
|
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-
|
11
|
+
date: 2021-11-10 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
|