database_consistency 1.1.7 → 1.1.12

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: 2a742a08f374228e004b155fef15ec5ddaa23404c5aacf42b462eb2cb82ba09a
4
- data.tar.gz: 8359e199cdbb89fc9d4b8700728bbef938d2d90a1474e4c2400c2aaa6d31f28f
3
+ metadata.gz: 908211c725197dadbe72f2f7c8f2f47d48a55ed546c57d2f512b9b2978fb325a
4
+ data.tar.gz: 4b18e433573c598b25906dce98554516f3c54bacbd897b59c8f72c6d9577a53d
5
5
  SHA512:
6
- metadata.gz: 962c814731ed2c85427e4b3e765df897c8cd8574f6075e3566e65b72af5effa370a14593019748ff9833a9658a0e55841219acdf3fe9caf212aa9db4bc426df3
7
- data.tar.gz: df3aab9a1b6b5d5b2a815ad237b76ff3ffe127cd7921050c09a57e5f53e08087344ad5777224a603c52978382f6568c0c8a19c16038863cb759cac147bb7f9be
6
+ metadata.gz: 43ea449cc58c970f99deb81936461d2f267a107934ad93cfb1f73ef0e0a8e46c97d9ba5085a54538828d162ca06638ad35afb907fa51de661df30bad9527cefc
7
+ data.tar.gz: 799f1975507dababf597ca140655377e90a1480af4422080349027b03ef7ef9dbade4125e95f317ef3d873706e82f1c24991c9c9600a08cb3dca3e6ff2bbc8e0
@@ -9,14 +9,21 @@ 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?
19
- return false if ActiveRecord::VERSION::MAJOR < 5 && ActiveRecord::Base.connection_config[:adapter] == 'sqlite3'
26
+ return false if ActiveRecord::VERSION::MAJOR < 5 && Helper.adapter == 'sqlite3'
20
27
 
21
28
  true
22
29
  end
@@ -2,18 +2,9 @@
2
2
 
3
3
  module DatabaseConsistency
4
4
  module Checkers
5
- # This class checks if association's foreign key type is the same as associated model's primary key
5
+ # This class checks if association's foreign key type covers associated model's primary key (same or bigger)
6
6
  class ForeignKeyTypeChecker < AssociationChecker
7
- INCONSISTENT_TYPE = 'associated model key (%a_f) with type (%a_t) mismatches key (%b_f) with type (%b_t)'
8
-
9
- TYPES = {
10
- 'serial' => 'integer',
11
- 'integer' => 'integer',
12
- 'int' => 'integer',
13
- 'bigserial' => 'bigint',
14
- 'bigint' => 'bigint',
15
- 'bigint unsigned' => 'bigint unsigned'
16
- }.freeze
7
+ INCONSISTENT_TYPE = "foreign key (%a_f) with type (%a_t) doesn't cover primary key (%b_f) with type (%b_t)"
17
8
 
18
9
  private
19
10
 
@@ -32,12 +23,12 @@ module DatabaseConsistency
32
23
  end
33
24
 
34
25
  # Table of possible statuses
35
- # | type | status |
36
- # | ------------ | ------ |
37
- # | consistent | ok |
38
- # | inconsistent | fail |
26
+ # | type | status |
27
+ # | ------------- | ------ |
28
+ # | covers | ok |
29
+ # | doesn't cover | fail |
39
30
  def check
40
- if converted_type(base_column) == converted_type(associated_column)
31
+ if converted_type(associated_column).cover?(converted_type(primary_column))
41
32
  report_template(:ok)
42
33
  else
43
34
  report_template(:fail, render_text)
@@ -51,40 +42,40 @@ module DatabaseConsistency
51
42
  INCONSISTENT_TYPE
52
43
  .gsub('%a_t', type(associated_column))
53
44
  .gsub('%a_f', associated_key)
54
- .gsub('%b_t', type(base_column))
55
- .gsub('%b_f', base_key)
45
+ .gsub('%b_t', type(primary_column))
46
+ .gsub('%b_f', primary_key)
56
47
  end
57
48
 
58
49
  # @return [String]
59
- def base_key
60
- @base_key ||= (
61
- if belongs_to_association?
62
- association.foreign_key
63
- else
64
- association.active_record_primary_key
65
- end
66
- ).to_s
50
+ def primary_key
51
+ @primary_key ||= if belongs_to_association?
52
+ association.association_primary_key
53
+ else
54
+ association.active_record_primary_key
55
+ end.to_s
67
56
  end
68
57
 
69
58
  # @return [String]
70
59
  def associated_key
71
- @associated_key ||= (
72
- if belongs_to_association?
73
- association.association_primary_key
74
- else
75
- association.foreign_key
76
- end
77
- ).to_s
60
+ @associated_key ||= association.foreign_key.to_s
78
61
  end
79
62
 
80
63
  # @return [ActiveRecord::ConnectionAdapters::Column]
81
- def base_column
82
- @base_column ||= column(association.active_record, base_key)
64
+ def primary_column
65
+ @primary_column ||= if belongs_to_association?
66
+ column(association.klass, primary_key)
67
+ else
68
+ column(association.active_record, primary_key)
69
+ end
83
70
  end
84
71
 
85
72
  # @return [ActiveRecord::ConnectionAdapters::Column]
86
73
  def associated_column
87
- @associated_column ||= column(association.klass, associated_key)
74
+ @associated_column ||= if belongs_to_association?
75
+ column(association.active_record, associated_key)
76
+ else
77
+ column(association.klass, associated_key)
78
+ end
88
79
  end
89
80
 
90
81
  # @return [DatabaseConsistency::Databases::Factory]
@@ -116,9 +107,9 @@ module DatabaseConsistency
116
107
 
117
108
  # @param [ActiveRecord::ConnectionAdapters::Column]
118
109
  #
119
- # @return [String]
110
+ # @return [DatabaseConsistency::Databases::Types::Base]
120
111
  def converted_type(column)
121
- database_factory.type(type(column)).convert
112
+ database_factory.type(type(column))
122
113
  end
123
114
 
124
115
  # @return [Boolean]
@@ -18,7 +18,11 @@ module DatabaseConsistency
18
18
 
19
19
  # We skip the check when there are no presence validators
20
20
  def preconditions
21
- validators.any?
21
+ validators.any? && !association?
22
+ end
23
+
24
+ def association?
25
+ model._reflect_on_association(attribute)&.macro == :has_one
22
26
  end
23
27
 
24
28
  # Table of possible statuses
@@ -34,13 +38,13 @@ module DatabaseConsistency
34
38
  report_template(:fail, e.message)
35
39
  end
36
40
 
37
- def has_weak_option?
41
+ def weak_option?
38
42
  validators.all? { |validator| validator.options.slice(*WEAK_OPTIONS).any? }
39
43
  end
40
44
 
41
45
  def report_message
42
46
  can_be_null = column.null
43
- has_weak_option = has_weak_option?
47
+ has_weak_option = weak_option?
44
48
 
45
49
  return report_template(:ok) if can_be_null == has_weak_option
46
50
  return report_template(:fail, POSSIBLE_NULL) unless can_be_null
@@ -53,8 +57,9 @@ module DatabaseConsistency
53
57
  end
54
58
 
55
59
  def 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")
60
+ @column ||= regular_column ||
61
+ association_reference_column ||
62
+ (raise Errors::MissingField, "column (#{attribute}) is missing in table (#{model.table_name}) but used for presence validation") # rubocop:disable Layout/LineLength
58
63
  end
59
64
 
60
65
  def regular_column
@@ -11,7 +11,7 @@ module DatabaseConsistency
11
11
  @configuration = Array(filepaths).each_with_object({}) do |filepath, result|
12
12
  content =
13
13
  if filepath && File.exist?(filepath)
14
- data = YAML.load_file(filepath)
14
+ data = load_yaml_config_file(filepath)
15
15
  data.is_a?(Hash) ? data : {}
16
16
  else
17
17
  {}
@@ -53,6 +53,14 @@ module DatabaseConsistency
53
53
 
54
54
  attr_reader :configuration
55
55
 
56
+ def load_yaml_config_file(filepath)
57
+ if YAML.respond_to?(:safe_load_file)
58
+ YAML.safe_load_file(filepath, aliases: true)
59
+ else
60
+ YAML.load_file(filepath)
61
+ end
62
+ end
63
+
56
64
  def combine_configs!(config, new_config)
57
65
  config.merge!(new_config) do |_key, val, new_val|
58
66
  if val.is_a?(Hash) && new_val.is_a?(Hash)
@@ -7,6 +7,11 @@ module DatabaseConsistency
7
7
  class Base
8
8
  attr_reader :type
9
9
 
10
+ COVERED_TYPES = {
11
+ 'bigint' => %w[integer bigint],
12
+ 'integer' => %w[integer smallint]
13
+ }.freeze
14
+
10
15
  # @param [String] type
11
16
  def initialize(type)
12
17
  @type = type
@@ -16,6 +21,13 @@ module DatabaseConsistency
16
21
  def convert
17
22
  type
18
23
  end
24
+
25
+ # @param [DatabaseConsistency::Databases::Types::Base]
26
+ #
27
+ # @return [Boolean]
28
+ def cover?(other_type)
29
+ (COVERED_TYPES[convert] || [convert]).include?(other_type.convert)
30
+ end
19
31
  end
20
32
  end
21
33
  end
@@ -7,9 +7,10 @@ module DatabaseConsistency
7
7
  class Sqlite < Base
8
8
  TYPES = {
9
9
  'bigserial' => 'bigint',
10
- 'bigint' => 'bigint',
11
10
  'serial' => 'integer',
12
- 'integer' => 'integer'
11
+ 'integer(8)' => 'bigint',
12
+ 'integer(4)' => 'integer',
13
+ 'integer(2)' => 'smallint'
13
14
  }.freeze
14
15
 
15
16
  # @return [String]
@@ -5,6 +5,22 @@ module DatabaseConsistency
5
5
  module Helper
6
6
  module_function
7
7
 
8
+ def adapter
9
+ if ActiveRecord::Base.respond_to?(:connection_config)
10
+ ActiveRecord::Base.connection_config[:adapter]
11
+ else
12
+ ActiveRecord::Base.connection_db_config.configuration_hash[:adapter]
13
+ end
14
+ end
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
+
8
24
  # Returns list of models to check
9
25
  def models
10
26
  ActiveRecord::Base.descendants.delete_if(&:abstract_class?).delete_if do |klass|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatabaseConsistency
4
- VERSION = '1.1.7'
4
+ VERSION = '1.1.12'
5
5
  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.7
4
+ version: 1.1.12
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-12-08 00:00:00.000000000 Z
11
+ date: 2022-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -56,14 +56,14 @@ dependencies:
56
56
  name: pg
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0.2'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.2'
69
69
  - !ruby/object:Gem::Dependency
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec_junit_formatter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.4'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rubocop
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -185,7 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
199
  - !ruby/object:Gem::Version
186
200
  version: '0'
187
201
  requirements: []
188
- rubygems_version: 3.0.8
202
+ rubygems_version: 3.2.22
189
203
  signing_key:
190
204
  specification_version: 4
191
205
  summary: Provide an easy way to check the consistency of the database constraints