database_consistency 2.0.8 → 2.1.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: 3093f4a5d4db53c187939d87a5799b5a932d9ddb6d7c4d124949e66e2ea14477
4
- data.tar.gz: d7c73224a9f1006113ad57b8a6a740f5198bcbe2ba7b855cdaac9d34b8794f87
3
+ metadata.gz: 347875b9be8806850702674f72e235f318f9c307bc915370fa940f3c23476e1d
4
+ data.tar.gz: b19f093bc18afb4be2f47b3309f9d8bd09f786b774d9226421e2856ec87a63e4
5
5
  SHA512:
6
- metadata.gz: e0b3a3e3507c77692ffcd1b89430e561bf9c51f1d5419ab5cd176667048c747d03bf9ca0789a60bd02e5e2deac6e666556f0d1c4cc95c666c66b4ee48562e0f6
7
- data.tar.gz: 3fa45f23b358a9ce3ab83be7512c6ec7d59c9ae6bf7b5ec39c50f26ddaa0063fb7a31dd2779d67e946222ef7aea0186d1ad1b7383a4c482424b01c6dda1348b4
6
+ metadata.gz: af8ea0a3e3e1ab9069a9db551601127d2fb82899a315eb40d2bdab4698f134704e248dce76826924b598755f94eb00280ebc15374189987da81cc748a9565ced
7
+ data.tar.gz: a2348924c764f4ee1d1d880aff03e3414ba9f2c62c4aba2c8b415bc52e92a282a6608e5da768b90468fcae0cf7b618bf4469fc86c0a1c1c5a6b7c2b301ca6079
@@ -23,6 +23,13 @@ module DatabaseConsistency
23
23
  def table_or_model_name
24
24
  @table_or_model_name ||= model.name.to_s
25
25
  end
26
+
27
+ def foreign_key_exists? # rubocop:disable Metrics/AbcSize
28
+ model.connection.foreign_keys(model.table_name).any? do |foreign_key|
29
+ (Helper.extract_columns(association.foreign_key.to_s) - Array.wrap(foreign_key.column)).empty? &&
30
+ foreign_key.to_table == association.klass.table_name
31
+ end
32
+ end
26
33
  end
27
34
  end
28
35
  end
@@ -42,13 +42,8 @@ module DatabaseConsistency
42
42
  # | ----------- | ------ |
43
43
  # | persisted | ok |
44
44
  # | missing | fail |
45
- def check # rubocop:disable Metrics/AbcSize
46
- fk_exist = model.connection.foreign_keys(model.table_name).any? do |fk|
47
- (Helper.extract_columns(association.foreign_key.to_s) - Array.wrap(fk.column)).empty? &&
48
- fk.to_table == association.klass.table_name
49
- end
50
-
51
- if fk_exist
45
+ def check
46
+ if foreign_key_exists?
52
47
  report_template(:ok)
53
48
  else
54
49
  report_template(:fail, error_slug: :missing_foreign_key)
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Checkers
5
+ # This class checks for models that need a dependent destroy association
6
+ class MissingDependentDestroyChecker < AssociationChecker
7
+ Report = ReportBuilder.define(
8
+ DatabaseConsistency::Report,
9
+ :model_name,
10
+ :attribute_name
11
+ )
12
+
13
+ DEPENDENT_OPTIONS = %i[destroy delete delete_all nullify].freeze
14
+
15
+ private
16
+
17
+ def preconditions
18
+ association.belongs_to? && foreign_key_exists?
19
+ end
20
+
21
+ def check
22
+ if dependent_destroy_exists? || cascade?
23
+ report_template(:ok)
24
+ else
25
+ report_template(:fail, error_slug: :missing_dependent_destroy)
26
+ end
27
+ end
28
+
29
+ def dependent_destroy_exists?
30
+ association.class_name.constantize.reflect_on_all_associations.any? do |association|
31
+ %i[has_many has_one].include?(association.macro) &&
32
+ DEPENDENT_OPTIONS.include?(association.options[:dependent]) &&
33
+ association.table_name == model.table_name
34
+ end
35
+ end
36
+
37
+ def foreign_key
38
+ association.klass
39
+ .connection
40
+ .foreign_keys(model.table_name)
41
+ .find { |fk| fk.column == association.foreign_key.to_s }
42
+ end
43
+
44
+ def cascade?
45
+ %i[cascade nullify].include? foreign_key.options[:on_delete]
46
+ end
47
+
48
+ def report_template(status, error_slug: nil)
49
+ Report.new(
50
+ status: status,
51
+ error_message: nil,
52
+ error_slug: error_slug,
53
+ model_name: association.class_name,
54
+ attribute_name: model.table_name,
55
+ **report_attributes
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
@@ -28,7 +28,7 @@ module DatabaseConsistency
28
28
  # | persisted | ok |
29
29
  # | missing | fail |
30
30
  def check
31
- if unique_index
31
+ if unique_index || primary_key_covers_validation?
32
32
  report_template(:ok)
33
33
  else
34
34
  report_template(:fail, error_slug: :missing_unique_index)
@@ -52,6 +52,14 @@ module DatabaseConsistency
52
52
  end
53
53
  end
54
54
 
55
+ def primary_key_covers_validation?
56
+ primary_key = model.connection.primary_key(model.table_name)
57
+
58
+ return false if primary_key.blank?
59
+
60
+ sorted_uniqueness_validator_columns == Helper.extract_columns(primary_key).sort
61
+ end
62
+
55
63
  def sorted_uniqueness_validator_columns
56
64
  @sorted_uniqueness_validator_columns ||= Helper.sorted_uniqueness_validator_columns(attribute, validator, model)
57
65
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DatabaseConsistency
4
- VERSION = '2.0.8'
4
+ VERSION = '2.1.0'
5
5
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DatabaseConsistency
4
+ module Writers
5
+ module Simple
6
+ class MissingDependentDestroy < Base # :nodoc:
7
+ private
8
+
9
+ def template
10
+ 'should have a corresponding has_one/has_many association with dependent option (destroy, delete, delete_all, nullify) or a foreign key with on_delete (cascade, nullify)' # rubocop:disable Layout/LineLength
11
+ end
12
+
13
+ def unique_attributes
14
+ {
15
+ model_name: report.model_name,
16
+ attribute_name: report.attribute_name
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -43,6 +43,7 @@ require 'database_consistency/writers/simple/three_state_boolean'
43
43
  require 'database_consistency/writers/simple/missing_association_class'
44
44
  require 'database_consistency/writers/simple/missing_table'
45
45
  require 'database_consistency/writers/simple/implicit_order_column_missing'
46
+ require 'database_consistency/writers/simple/missing_dependent_destroy'
46
47
  require 'database_consistency/writers/simple_writer'
47
48
 
48
49
  require 'database_consistency/writers/autofix/helpers/migration'
@@ -83,6 +84,7 @@ require 'database_consistency/checkers/association_checkers/foreign_key_checker'
83
84
  require 'database_consistency/checkers/association_checkers/foreign_key_type_checker'
84
85
  require 'database_consistency/checkers/association_checkers/foreign_key_cascade_checker'
85
86
  require 'database_consistency/checkers/association_checkers/missing_association_class_checker'
87
+ require 'database_consistency/checkers/association_checkers/missing_dependent_destroy_checker'
86
88
 
87
89
  require 'database_consistency/checkers/column_checkers/column_checker'
88
90
  require 'database_consistency/checkers/column_checkers/null_constraint_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: 2.0.8
4
+ version: 2.1.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: 2025-11-12 00:00:00.000000000 Z
11
+ date: 2025-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -151,6 +151,7 @@ files:
151
151
  - lib/database_consistency/checkers/association_checkers/foreign_key_checker.rb
152
152
  - lib/database_consistency/checkers/association_checkers/foreign_key_type_checker.rb
153
153
  - lib/database_consistency/checkers/association_checkers/missing_association_class_checker.rb
154
+ - lib/database_consistency/checkers/association_checkers/missing_dependent_destroy_checker.rb
154
155
  - lib/database_consistency/checkers/association_checkers/missing_index_checker.rb
155
156
  - lib/database_consistency/checkers/base_checker.rb
156
157
  - lib/database_consistency/checkers/column_checkers/column_checker.rb
@@ -225,6 +226,7 @@ files:
225
226
  - lib/database_consistency/writers/simple/length_validator_lower_limit.rb
226
227
  - lib/database_consistency/writers/simple/length_validator_missing.rb
227
228
  - lib/database_consistency/writers/simple/missing_association_class.rb
229
+ - lib/database_consistency/writers/simple/missing_dependent_destroy.rb
228
230
  - lib/database_consistency/writers/simple/missing_foreign_key.rb
229
231
  - lib/database_consistency/writers/simple/missing_foreign_key_cascade.rb
230
232
  - lib/database_consistency/writers/simple/missing_table.rb
@@ -273,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
273
275
  - !ruby/object:Gem::Version
274
276
  version: '0'
275
277
  requirements: []
276
- rubygems_version: 3.4.1
278
+ rubygems_version: 3.3.22
277
279
  signing_key:
278
280
  specification_version: 4
279
281
  summary: Provide an easy way to check the consistency of the database constraints