database_consistency 1.1.11 → 1.1.15

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: f837d273af4845f139d3dc53fd3131d4224383576939984865480b65a022ad07
4
- data.tar.gz: acba58e69f8a8a8b2083318e983bac226c0681fb5925e927a412fee573ccdc7b
3
+ metadata.gz: e7986728aea3224bf5a8f04ef65847f88bfe517b4c7b0b3b4361c7a0dbdd2a2d
4
+ data.tar.gz: d7225b7dadd93850c02c0282974dc01d4c8ae6c2ded3638e996d6aa3fe29fdbe
5
5
  SHA512:
6
- metadata.gz: 386730f70655e59069f9d90a42a8dcba7d4ed9fefb61ac0d6abcd56bce725be7a699441f7d8b357964c773e06f3d362c6d289d1dfc19c1e334d1b2e956e64875
7
- data.tar.gz: b37bee82b425c808658369824084fa92a93ff9a733464303b0343bfbf42f6c493286edafd87d051b78810c1d6b5d6eb85ba2fb09d637f10dca9bb22e35dce283
6
+ metadata.gz: ed7beed1d43e74309e173bfba69ebb82dc4948b73b31413c43d7454a4f3c165ef68328d902278bf8e1bf527897da9848213f477779f3a48d198a580a17b8f9ef
7
+ data.tar.gz: 0f00c0005e59a6f374c58d25b3554405edf78eb592908603b46224ca7aff86c0e9d39e2a1bb642d6ea0a69100d8df0bf8564c184e8d3ee4b88f93cfdafa75fb1
@@ -7,6 +7,7 @@ module DatabaseConsistency
7
7
  attr_reader :model, :association
8
8
 
9
9
  def initialize(model, association)
10
+ super()
10
11
  @model = model
11
12
  @association = association
12
13
  end
@@ -9,10 +9,17 @@ module DatabaseConsistency
9
9
  private
10
10
 
11
11
  # We skip check when:
12
+ # - underlying models belong to different databases
12
13
  # - association isn't belongs_to association
13
14
  # - association is polymorphic
14
15
  def preconditions
15
- supported? && association.belongs_to? && !association.polymorphic?
16
+ supported? &&
17
+ association.belongs_to? && !association.polymorphic? &&
18
+ same_database?
19
+ end
20
+
21
+ def same_database?
22
+ Helper.connection_config(model) == Helper.connection_config(association.klass)
16
23
  end
17
24
 
18
25
  def supported?
@@ -6,6 +6,7 @@ module DatabaseConsistency
6
6
  class MissingIndexChecker < AssociationChecker
7
7
  # Message templates
8
8
  MISSING_INDEX = 'associated model should have proper index in the database'
9
+ MISSING_UNIQUE_INDEX = 'associated model should have proper unique index in the database'
9
10
 
10
11
  private
11
12
 
@@ -28,6 +29,22 @@ module DatabaseConsistency
28
29
  # | persisted | ok |
29
30
  # | missing | fail |
30
31
  def check
32
+ if unique_has_one_association?
33
+ check_unique_has_one
34
+ else
35
+ check_remaining
36
+ end
37
+ end
38
+
39
+ def check_unique_has_one
40
+ if unique_index
41
+ report_template(:ok)
42
+ else
43
+ report_template(:fail, MISSING_UNIQUE_INDEX)
44
+ end
45
+ end
46
+
47
+ def check_remaining
31
48
  if index
32
49
  report_template(:ok)
33
50
  else
@@ -35,9 +52,19 @@ module DatabaseConsistency
35
52
  end
36
53
  end
37
54
 
55
+ def unique_has_one_association?
56
+ association.scope.nil? && association.macro == :has_one && !association.options[:as].present?
57
+ end
58
+
59
+ def unique_index
60
+ @unique_index ||= association.klass.connection.indexes(association.klass.table_name).find do |index|
61
+ index_keys(index) == association_keys && index.unique
62
+ end
63
+ end
64
+
38
65
  def index
39
66
  @index ||= association.klass.connection.indexes(association.klass.table_name).find do |index|
40
- index_keys(index) == association_keys
67
+ index_keys(index, limit: association_keys.size) == association_keys
41
68
  end
42
69
  end
43
70
 
@@ -45,10 +72,16 @@ module DatabaseConsistency
45
72
  @association_keys ||= [association.foreign_key, association.type].compact.map(&:to_s).sort
46
73
  end
47
74
 
48
- def index_keys(index)
75
+ def index_keys(index, limit: nil)
49
76
  return unless index.columns.is_a?(Array)
50
77
 
51
- index.columns[0...association_keys.size].sort
78
+ columns = index.columns
79
+
80
+ if limit
81
+ columns.first(limit).sort
82
+ else
83
+ columns
84
+ end
52
85
  end
53
86
  end
54
87
  end
@@ -19,7 +19,7 @@ module DatabaseConsistency
19
19
  # @param [Boolean] catch_errors
20
20
  #
21
21
  # @return [Hash, File, nil]
22
- def report(catch_errors = true)
22
+ def report(catch_errors: true)
23
23
  return unless preconditions
24
24
 
25
25
  @report ||= check
@@ -7,6 +7,7 @@ module DatabaseConsistency
7
7
  attr_reader :model, :column
8
8
 
9
9
  def initialize(model, column)
10
+ super()
10
11
  @model = model
11
12
  @column = column
12
13
  end
@@ -7,6 +7,7 @@ module DatabaseConsistency
7
7
  attr_reader :model, :index
8
8
 
9
9
  def initialize(model, index)
10
+ super()
10
11
  @model = model
11
12
  @index = index
12
13
  end
@@ -7,6 +7,7 @@ module DatabaseConsistency
7
7
  attr_reader :model, :attribute, :validator
8
8
 
9
9
  def initialize(model, attribute, validator)
10
+ super()
10
11
  @model = model
11
12
  @attribute = attribute
12
13
  @validator = validator
@@ -7,6 +7,7 @@ module DatabaseConsistency
7
7
  attr_reader :model, :attribute, :validators
8
8
 
9
9
  def initialize(model, attribute, validators)
10
+ super()
10
11
  @model = model
11
12
  @attribute = attribute
12
13
  @validators = validators.select(&method(:filter))
@@ -13,10 +13,20 @@ module DatabaseConsistency
13
13
  end
14
14
  end
15
15
 
16
+ def connection_config(klass)
17
+ if klass.respond_to?(:connection_config)
18
+ klass.connection_config
19
+ else
20
+ klass.connection_db_config.configuration_hash
21
+ end
22
+ end
23
+
16
24
  # Returns list of models to check
17
25
  def models
18
- ActiveRecord::Base.descendants.delete_if(&:abstract_class?).delete_if do |klass|
19
- !klass.connection.table_exists?(klass.table_name) || klass.name.include?('HABTM_')
26
+ ActiveRecord::Base.descendants.delete_if(&:abstract_class?).select do |klass|
27
+ klass.connection.table_exists?(klass.table_name) &&
28
+ !klass.name.include?('HABTM_') &&
29
+ project_klass?(klass)
20
30
  end
21
31
  end
22
32
 
@@ -27,6 +37,15 @@ module DatabaseConsistency
27
37
  end
28
38
  end
29
39
 
40
+ # @param klass [ActiveRecord::Base]
41
+ #
42
+ # @return [Boolean]
43
+ def project_klass?(klass)
44
+ return true unless Module.respond_to?(:const_source_location) && defined?(Bundler)
45
+
46
+ !Module.const_source_location(klass.to_s).first.to_s.include?(Bundler.bundle_path.to_s)
47
+ end
48
+
30
49
  # @return [Boolean]
31
50
  def check_inclusion?(array, element)
32
51
  array.include?(element.to_s) || array.include?(element.to_sym)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatabaseConsistency
4
- VERSION = '1.1.11'
4
+ VERSION = '1.1.15'
5
5
  end
@@ -12,6 +12,12 @@ module DatabaseConsistency
12
12
  red: "\e[31m"
13
13
  }.freeze
14
14
 
15
+ COLOR_BY_STATUS = {
16
+ ok: :green,
17
+ warning: :yellow,
18
+ fail: :red
19
+ }.freeze
20
+
15
21
  def write
16
22
  results.each do |result|
17
23
  next unless write?(result.status)
@@ -31,11 +37,7 @@ module DatabaseConsistency
31
37
  end
32
38
 
33
39
  def status_text(result)
34
- color = case result.status
35
- when :ok then :green
36
- when :warning then :yellow
37
- when :fail then :red
38
- end
40
+ color = COLOR_BY_STATUS[result.status]
39
41
 
40
42
  colorize(result.status, color)
41
43
  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: 1.1.11
4
+ version: 1.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-15 00:00:00.000000000 Z
11
+ date: 2022-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -199,7 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
199
  - !ruby/object:Gem::Version
200
200
  version: '0'
201
201
  requirements: []
202
- rubygems_version: 3.2.22
202
+ rubygems_version: 3.1.6
203
203
  signing_key:
204
204
  specification_version: 4
205
205
  summary: Provide an easy way to check the consistency of the database constraints