database_consistency 0.1.0 → 0.2.0

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: 814513a9fa9c4a886a0181cbb09e71fb35ed3ec722404746f827fe754067df01
4
- data.tar.gz: 1638aee8d2c92c761905e6a0b433581d6f996bb3f7c871dc2a75c84956cbb12c
3
+ metadata.gz: c50d282f04ae0e4003a596551369213ea66ee986a6f2486a3761ec36af6d87b3
4
+ data.tar.gz: 14141f85bb9ced24c2cf4fe69d2ace3a0aa0218e4f181846d2c0dfcf88569d9d
5
5
  SHA512:
6
- metadata.gz: 47ef92e9038f22b807588f560e3c66f95a776e8c07b47633b8f6352935ffdb2bf8e22e6f21178b9ca1a946d84ab345fb4fdf600f2d69bed5935bdf7c5e328eea
7
- data.tar.gz: feb38ceb958dc96139b4cca1a3dd70d884c4955203227a0f4d7402ee7d3c0128983c3205f414590829eae508a9d412cd2fd67a80c955b318a327b50cb2b6189f
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: :comparison
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 comparison
17
- Comparison.for(validator, column)
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
- CONSTRAINT_MISSING = 'database field should have: "null: false"'.freeze
7
- POSSIBLE_NULL = 'possible null value insert'.freeze
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 begin
3
- class Processor
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 comparisons
9
- Helper.models.each_with_object({}) do |model, hash|
10
- hash[model.name] = model.validators.flat_map do |validator|
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.compact
19
- end
18
+ end
19
+ end.compact
20
20
  end
21
21
  end
22
22
  end
@@ -1,3 +1,3 @@
1
1
  module DatabaseConsistency
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -10,7 +10,11 @@ module DatabaseConsistency
10
10
  end
11
11
 
12
12
  def write?(status)
13
- status == :fail || log_level == 'DEBUG'
13
+ status == :fail
14
+ end
15
+
16
+ def debug?
17
+ log_level == 'DEBUG'
14
18
  end
15
19
 
16
20
  def self.write(results, log_level)
@@ -8,18 +8,20 @@ module DatabaseConsistency
8
8
  end
9
9
 
10
10
  def format
11
- results.map do |model_name, comparisons|
12
- comparisons.map do |comparison|
13
- next unless write?(comparison[:status])
14
- line(model_name, comparison)
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 line(model_name, comparison)
20
- <<-TEXT
21
- #{comparison[:status]} #{comparison[:message]} #{model_name} #{comparison[:validator].inspect} #{comparison[:column].inspect}
22
- TEXT
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
@@ -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
- require 'database_consistency/comparison'
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/processor'
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
- Processor.new.comparisons,
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.1.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-30 00:00:00.000000000 Z
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/comparison.rb
117
+ - lib/database_consistency/database_processor.rb
116
118
  - lib/database_consistency/helper.rb
117
- - lib/database_consistency/processor.rb
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