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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc034a38ab80a2e277860a5a69f6a654e1e461f691f54d6a510814b55279cebd
|
4
|
+
data.tar.gz: 88055bcbcb73bc260ef4718006f3149d95ea216badb4bd4ac142506e756c1882
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
213
|
-
|
214
|
-
|
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)
|
@@ -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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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)
|