bulk_dependency_eraser 1.0.3 → 1.0.4

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: dc8c21921516530d646fff41d72ce0157e1d706373eefea4da7ea924bb1cb9b9
4
- data.tar.gz: 9501007142223dfad5cb05e89ab38162499b564eaaf3636074e3cd54a573592f
3
+ metadata.gz: cc034a38ab80a2e277860a5a69f6a654e1e461f691f54d6a510814b55279cebd
4
+ data.tar.gz: 88055bcbcb73bc260ef4718006f3149d95ea216badb4bd4ac142506e756c1882
5
5
  SHA512:
6
- metadata.gz: 0f461d596eb9160828f0905dde68396ade1409f8f9c17de2e4bb8677cb12695be59c75f6fa33d84d9156a2b10fdab2eed869b7f19a79c84e1526c705ac4cf58b
7
- data.tar.gz: 64777768e6eb815d575d11690cb793962ab4fcb24911bc2bb209d5d7a33d3bc660b6d939fe287ca2c41dcac8524efe95032f3b6ee76272956391589193315666
6
+ metadata.gz: 0c9d1bc7851eaa2f51a853a99b24ff3842940f792938b2eac86ebfcc6471653c0d14de735d837f108ca59118a6661c086566b48475b87f1c98870cd80544dd79
7
+ data.tar.gz: 7e09f55e2baf0db2eefd7f2dfc028fda58b7f9ec2469a6bdbcfa56855bd4cf1ddc0b1502468554f56726fcbd08135daecc5e20940d18b2d9a2f49dc2558c5971
@@ -209,19 +209,24 @@ module BulkDependencyEraser
209
209
  nullify_association_names = nullify_associations.map(&:name)
210
210
  restricted_association_names = restricted_associations.map(&:name)
211
211
 
212
- if opts_c.verbose
213
- puts "Destroyable Associations: #{destroy_association_names}"
214
- puts "Nullifiable Associations: #{nullify_association_names}"
215
- puts " Restricted Associations: #{restricted_association_names}"
216
- end
217
-
218
- # Iterate through the assoc names, if there are any :through assocs, then remap
212
+ # Iterate through the assoc names, if there are any :through assocs, then rename the association
213
+ # - Rails interpretation of any dependencies of a :through association is to apply it to
214
+ # the leaf association at the end of the :through chain(s)
219
215
  destroy_association_names = destroy_association_names.collect do |assoc_name|
220
216
  find_root_association_from_through_assocs(klass, assoc_name)
221
217
  end
222
218
  nullify_association_names = nullify_association_names.collect do |assoc_name|
223
219
  find_root_association_from_through_assocs(klass, assoc_name)
224
220
  end
221
+ restricted_association_names = restricted_association_names.collect do |assoc_name|
222
+ find_root_association_from_through_assocs(klass, assoc_name)
223
+ end
224
+
225
+ if opts_c.verbose
226
+ puts "Destroyable Associations: #{destroy_association_names}"
227
+ puts "Nullifiable Associations: #{nullify_association_names}"
228
+ puts " Restricted Associations: #{restricted_association_names}"
229
+ end
225
230
 
226
231
  destroy_association_names.each do |destroy_association_name|
227
232
  association_parser(klass, query, query_ids, destroy_association_name, :delete)
@@ -24,8 +24,7 @@ module BulkDependencyEraser
24
24
  return false unless build
25
25
  end
26
26
 
27
- delete!
28
- nullify!
27
+ nullify! && delete!
29
28
 
30
29
  return errors.none?
31
30
  end
@@ -2,7 +2,11 @@ module BulkDependencyEraser
2
2
  class Nullifier < Base
3
3
  DEFAULT_OPTS = {
4
4
  verbose: false,
5
- db_nullify_wrapper: self::DEFAULT_DB_WRAPPER
5
+ db_nullify_wrapper: self::DEFAULT_DB_WRAPPER,
6
+ # Set to true if you want 'ActiveRecord::InvalidForeignKey' errors raised during nullifications
7
+ # - I can't think of a use-case where a nullification would generate an invalid key error
8
+ # - Not hurting anything to leave it in, but might remove it in the future.
9
+ enable_invalid_foreign_key_detection: false
6
10
  }.freeze
7
11
 
8
12
  DEFAULT_DB_WRAPPER = ->(block) do
@@ -22,6 +26,53 @@ module BulkDependencyEraser
22
26
  def initialize class_names_columns_and_ids:, opts: {}
23
27
  @class_names_columns_and_ids = class_names_columns_and_ids
24
28
  super(opts:)
29
+
30
+ if opts_c.verbose
31
+ puts "Combining nullification column groups (if groupable)"
32
+ puts "Before Combination: #{@class_names_columns_and_ids}"
33
+ end
34
+
35
+ @class_names_columns_and_ids = combine_matching_columns(@class_names_columns_and_ids)
36
+
37
+ if opts_c.verbose
38
+ puts "After Combination: #{@class_names_columns_and_ids}"
39
+ end
40
+ end
41
+
42
+ # Combine columns if the IDs are the same
43
+ # - will do one SQL call instead of several
44
+ def combine_matching_columns(nullification_hash)
45
+ return {} if nullification_hash.none?
46
+
47
+ merged_hash = {}
48
+
49
+ nullification_hash.each do |klass_name, columns_and_ids|
50
+ merged_hash[klass_name] = {}
51
+ columns_and_ids.each do |key, array|
52
+ sorted_array = array.sort
53
+
54
+ # Find any existing key in merged_hash that has the same sorted array
55
+ matching_key = merged_hash[klass_name].keys.find { |k| merged_hash[klass_name][k].sort == sorted_array }
56
+
57
+ if matching_key
58
+ # Concatenate the matching keys and update the hash
59
+ new_key = key.is_a?(Array) ? key : [key]
60
+ if matching_key.is_a?(Array)
61
+ new_key += matching_key
62
+ else
63
+ new_key << matching_key
64
+ end
65
+
66
+ merged_hash[klass_name][new_key] = sorted_array
67
+ merged_hash[klass_name].delete(matching_key)
68
+ else
69
+ # Otherwise, just add the current key-value pair
70
+ merged_hash[klass_name][key] = sorted_array
71
+ end
72
+ end
73
+ end
74
+
75
+ merged_hash
25
76
  end
26
77
 
27
78
  def execute
@@ -34,15 +85,19 @@ module BulkDependencyEraser
34
85
  klass = class_name.constantize
35
86
 
36
87
  columns_and_ids = class_names_columns_and_ids[class_name]
37
-
38
88
  columns_and_ids.each do |column, ids|
39
89
  current_column = column
40
- # Disable any ActiveRecord::InvalidForeignKey raised errors.
41
- # src https://stackoverflow.com/questions/41005849/rails-migrations-temporarily-ignore-foreign-key-constraint
42
- # https://apidock.com/rails/ActiveRecord/ConnectionAdapters/AbstractAdapter/disable_referential_integrity
43
- ActiveRecord::Base.connection.disable_referential_integrity do
44
- nullify_in_db do
45
- klass.unscoped.where(id: ids).update_all(column => nil)
90
+
91
+ if opts_c.enable_invalid_foreign_key_detection
92
+ # nullify with referential integrity
93
+ nullify_by_klass_column_and_ids(klass, column, ids)
94
+ else
95
+ # nullify without referential integrity
96
+ # Disable any ActiveRecord::InvalidForeignKey raised errors.
97
+ # - src: https://stackoverflow.com/questions/41005849/rails-migrations-temporarily-ignore-foreign-key-constraint
98
+ # https://apidock.com/rails/ActiveRecord/ConnectionAdapters/AbstractAdapter/disable_referential_integrity
99
+ ActiveRecord::Base.connection.disable_referential_integrity do
100
+ nullify_by_klass_column_and_ids(klass, column, ids)
46
101
  end
47
102
  end
48
103
  end
@@ -60,6 +115,23 @@ module BulkDependencyEraser
60
115
 
61
116
  attr_reader :class_names_columns_and_ids
62
117
 
118
+ def nullify_by_klass_column_and_ids klass, columns, ids
119
+ nullify_columns = {}
120
+
121
+ # supporting nullification of groups of columns simultaneously
122
+ if columns.is_a?(Array)
123
+ columns.each do |column|
124
+ nullify_columns[column] = nil
125
+ end
126
+ else
127
+ nullify_columns[columns] = nil
128
+ end
129
+
130
+ nullify_in_db do
131
+ klass.unscoped.where(id: ids).update_all(nullify_columns)
132
+ end
133
+ end
134
+
63
135
  def nullify_in_db(&block)
64
136
  puts "Nullifying from DB..." if opts_c.verbose
65
137
  opts_c.db_nullify_wrapper.call(block)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bulk_dependency_eraser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - benjamin.dana.software.dev@gmail.com