database_consistency 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/database_consistency/column_verifiers/base_verifier.rb +23 -0
- data/lib/database_consistency/column_verifiers/presence_missing_verifier.rb +26 -0
- data/lib/database_consistency/comparators/base_comparator.rb +3 -5
- data/lib/database_consistency/comparators/presence_comparator.rb +12 -5
- data/lib/database_consistency/database_processor.rb +18 -0
- data/lib/database_consistency/helper.rb +7 -0
- data/lib/database_consistency/report.rb +17 -0
- data/lib/database_consistency/{processor.rb → validators_processor.rb} +7 -7
- data/lib/database_consistency/version.rb +1 -1
- data/lib/database_consistency/writers/base_writer.rb +5 -1
- data/lib/database_consistency/writers/simple_writer.rb +12 -10
- data/lib/database_consistency.rb +15 -4
- metadata +7 -4
- data/lib/database_consistency/comparison.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c50d282f04ae0e4003a596551369213ea66ee986a6f2486a3761ec36af6d87b3
|
4
|
+
data.tar.gz: 14141f85bb9ced24c2cf4fe69d2ace3a0aa0218e4f181846d2c0dfcf88569d9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90577c3faf083a0c694ac8d1146d5980e7ff69df6be7578cb57069bf62a4bc3455c2f8b4a639ccae2b75f8db8473c3c5e1733e407ca0e3292a5610062e48313b
|
7
|
+
data.tar.gz: 1d638396701af3be6591db67d5782cae92d4af14fb38a4a076834836b2b7988772ee053056247d56984f2830185dd9b7703464efabec21d99e8674b112b0abfa
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DatabaseConsistency
|
2
|
+
module ColumnVerifiers
|
3
|
+
# The base class for column verifiers
|
4
|
+
class BaseVerifier
|
5
|
+
attr_reader :model, :column
|
6
|
+
|
7
|
+
delegate :result, to: :report
|
8
|
+
|
9
|
+
def initialize(model, column)
|
10
|
+
@model = model
|
11
|
+
@column = column
|
12
|
+
end
|
13
|
+
|
14
|
+
def report
|
15
|
+
Report.new(column: column)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.verify(model, column)
|
19
|
+
new(model, column).verify
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DatabaseConsistency
|
2
|
+
module ColumnVerifiers
|
3
|
+
# This class verifies that column needs a presence validator
|
4
|
+
class PresenceMissingVerifier < BaseVerifier
|
5
|
+
VALIDATOR_MISSING = 'is required but do not have presence validator'.freeze
|
6
|
+
|
7
|
+
def verify
|
8
|
+
result(:fail, Helper.message(column, VALIDATOR_MISSING)) unless skip? || validator?
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def skip?
|
14
|
+
column.null ||
|
15
|
+
column.name == model.primary_key ||
|
16
|
+
(model.record_timestamps? && %w[created_at updated_at].include?(column.name))
|
17
|
+
end
|
18
|
+
|
19
|
+
def validator?
|
20
|
+
model.validators.grep(ActiveModel::Validations::PresenceValidator).any? do |validator|
|
21
|
+
validator.attributes.include?(column.name) || validator.attributes.include?(column.name.to_sym)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -4,17 +4,15 @@ module DatabaseConsistency
|
|
4
4
|
class BaseComparator
|
5
5
|
attr_reader :validator, :column
|
6
6
|
|
7
|
-
delegate :result, to: :
|
8
|
-
|
9
|
-
private_class_method :new
|
7
|
+
delegate :result, to: :report
|
10
8
|
|
11
9
|
def initialize(validator, column)
|
12
10
|
@validator = validator
|
13
11
|
@column = column
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
|
14
|
+
def report
|
15
|
+
Report.new(validator: validator, column: column)
|
18
16
|
end
|
19
17
|
|
20
18
|
def self.compare(validator, column)
|
@@ -3,8 +3,9 @@ module DatabaseConsistency
|
|
3
3
|
# The comparator class for {{ActiveModel::Validations::PresenceValidator}}
|
4
4
|
class PresenceComparator < BaseComparator
|
5
5
|
WEAK_OPTIONS = %i[allow_nil allow_blank if unless].freeze
|
6
|
-
|
7
|
-
|
6
|
+
# Message templates
|
7
|
+
CONSTRAINT_MISSING = 'should be required in the database'.freeze
|
8
|
+
POSSIBLE_NULL = 'is required but possible null value insert'.freeze
|
8
9
|
|
9
10
|
# Table of possible statuses
|
10
11
|
# | allow_nil/allow_blank/if/unless | database | status |
|
@@ -18,13 +19,19 @@ module DatabaseConsistency
|
|
18
19
|
has_weak_option = validator.options.slice(*WEAK_OPTIONS).any?
|
19
20
|
|
20
21
|
if can_be_null == has_weak_option
|
21
|
-
result(:ok)
|
22
|
+
result(:ok, message)
|
22
23
|
elsif can_be_null
|
23
|
-
result(:fail, CONSTRAINT_MISSING)
|
24
|
+
result(:fail, message(CONSTRAINT_MISSING))
|
24
25
|
else
|
25
|
-
result(:fail, POSSIBLE_NULL)
|
26
|
+
result(:fail, message(POSSIBLE_NULL))
|
26
27
|
end
|
27
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def message(template = nil)
|
33
|
+
Helper.message(column, template)
|
34
|
+
end
|
28
35
|
end
|
29
36
|
end
|
30
37
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module DatabaseConsistency
|
2
|
+
# The class to process missing validators
|
3
|
+
class DatabaseProcessor
|
4
|
+
VERIFIERS = [
|
5
|
+
ColumnVerifiers::PresenceMissingVerifier
|
6
|
+
].freeze
|
7
|
+
|
8
|
+
def reports
|
9
|
+
Helper.models.flat_map do |model|
|
10
|
+
model.columns.flat_map do |column|
|
11
|
+
VERIFIERS.map do |verifier|
|
12
|
+
verifier.verify(model, column)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end.compact
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -17,5 +17,12 @@ module DatabaseConsistency
|
|
17
17
|
def find_field(model, attribute)
|
18
18
|
model.columns.select.find { |field| field.name == attribute }
|
19
19
|
end
|
20
|
+
|
21
|
+
# @return [String]
|
22
|
+
def message(column, template = nil)
|
23
|
+
str = "column #{column.name} of table #{column.table_name}"
|
24
|
+
str += " #{template}" if template
|
25
|
+
str
|
26
|
+
end
|
20
27
|
end
|
21
28
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module DatabaseConsistency
|
2
|
+
# This class outputs the report result
|
3
|
+
class Report
|
4
|
+
attr_reader :opts
|
5
|
+
|
6
|
+
def initialize(opts = {})
|
7
|
+
@opts = opts
|
8
|
+
end
|
9
|
+
|
10
|
+
def result(status, message)
|
11
|
+
{
|
12
|
+
status: status,
|
13
|
+
message: message
|
14
|
+
}.tap { |hash| hash[:opts] = opts unless opts.empty? }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module DatabaseConsistency
|
2
|
-
# The class to
|
3
|
-
class
|
2
|
+
# The class to process all comparators
|
3
|
+
class ValidatorsProcessor
|
4
4
|
COMPARATORS = {
|
5
5
|
presence: DatabaseConsistency::Comparators::PresenceComparator
|
6
6
|
}.freeze
|
7
7
|
|
8
|
-
def
|
9
|
-
Helper.models.
|
10
|
-
|
8
|
+
def reports
|
9
|
+
Helper.models.flat_map do |model|
|
10
|
+
model.validators.flat_map do |validator|
|
11
11
|
next unless (comparator = COMPARATORS[validator.kind])
|
12
12
|
|
13
13
|
validator.attributes.map do |attribute|
|
@@ -15,8 +15,8 @@ module DatabaseConsistency
|
|
15
15
|
|
16
16
|
comparator.compare(validator, column)
|
17
17
|
end
|
18
|
-
end
|
19
|
-
end
|
18
|
+
end
|
19
|
+
end.compact
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -8,18 +8,20 @@ module DatabaseConsistency
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def format
|
11
|
-
results.map do |
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end.tap(&:compact!).map(&:lstrip).join("\n")
|
16
|
-
end.join("\n")
|
11
|
+
results.map do |result|
|
12
|
+
next unless write?(result[:status])
|
13
|
+
line(result)
|
14
|
+
end.tap(&:compact!).map(&:lstrip).delete_if(&:empty?).join(delimiter)
|
17
15
|
end
|
18
16
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
def delimiter
|
18
|
+
debug? ? "\n\n" : "\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
def line(result)
|
22
|
+
"#{result[:status]} #{result[:message]}".tap do |str|
|
23
|
+
str.concat " #{result[:opts].inspect}" if debug?
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
data/lib/database_consistency.rb
CHANGED
@@ -1,21 +1,32 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
|
3
3
|
require 'database_consistency/version'
|
4
|
+
require 'database_consistency/report'
|
5
|
+
require 'database_consistency/helper'
|
6
|
+
|
4
7
|
require 'database_consistency/writers/base_writer'
|
5
8
|
require 'database_consistency/writers/simple_writer'
|
6
|
-
|
7
|
-
require 'database_consistency/helper'
|
9
|
+
|
8
10
|
require 'database_consistency/comparators/base_comparator'
|
9
11
|
require 'database_consistency/comparators/presence_comparator'
|
10
|
-
require 'database_consistency/
|
12
|
+
require 'database_consistency/validators_processor'
|
13
|
+
|
14
|
+
require 'database_consistency/column_verifiers/base_verifier'
|
15
|
+
require 'database_consistency/column_verifiers/presence_missing_verifier'
|
16
|
+
require 'database_consistency/database_processor'
|
11
17
|
|
12
18
|
# The root module
|
13
19
|
module DatabaseConsistency
|
14
20
|
def self.run
|
15
21
|
Helper.load_environment!
|
16
22
|
|
23
|
+
reports = [
|
24
|
+
ValidatorsProcessor.new,
|
25
|
+
DatabaseProcessor.new
|
26
|
+
].flat_map(&:reports)
|
27
|
+
|
17
28
|
Writers::SimpleWriter.write(
|
18
|
-
|
29
|
+
reports,
|
19
30
|
ENV['LOG_LEVEL'] || 'INFO'
|
20
31
|
)
|
21
32
|
end
|
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: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeniy Demin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -110,11 +110,14 @@ extra_rdoc_files: []
|
|
110
110
|
files:
|
111
111
|
- bin/database_consistency
|
112
112
|
- lib/database_consistency.rb
|
113
|
+
- lib/database_consistency/column_verifiers/base_verifier.rb
|
114
|
+
- lib/database_consistency/column_verifiers/presence_missing_verifier.rb
|
113
115
|
- lib/database_consistency/comparators/base_comparator.rb
|
114
116
|
- lib/database_consistency/comparators/presence_comparator.rb
|
115
|
-
- lib/database_consistency/
|
117
|
+
- lib/database_consistency/database_processor.rb
|
116
118
|
- lib/database_consistency/helper.rb
|
117
|
-
- lib/database_consistency/
|
119
|
+
- lib/database_consistency/report.rb
|
120
|
+
- lib/database_consistency/validators_processor.rb
|
118
121
|
- lib/database_consistency/version.rb
|
119
122
|
- lib/database_consistency/writers/base_writer.rb
|
120
123
|
- lib/database_consistency/writers/simple_writer.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module DatabaseConsistency
|
2
|
-
# This class outputs the comparison result
|
3
|
-
class Comparison
|
4
|
-
attr_reader :validator, :column
|
5
|
-
|
6
|
-
private_class_method :new
|
7
|
-
|
8
|
-
def initialize(validator, column)
|
9
|
-
@validator = validator
|
10
|
-
@column = column
|
11
|
-
end
|
12
|
-
|
13
|
-
def result(status, message = nil)
|
14
|
-
{
|
15
|
-
column: column,
|
16
|
-
validator: validator,
|
17
|
-
status: status
|
18
|
-
}.tap { |hash| hash[:message] = message if message }
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.for(validator, column)
|
22
|
-
new(validator, column)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|