bulk_dependency_eraser 0.0.1 → 0.0.2
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: dca31bd9e7da64eaade636f74a6d787a1faacaf7f1489d8c2e3970443cd61c24
|
4
|
+
data.tar.gz: bd407ef3c87918562d28f350c5b3051406ef605c93bbbf55e017969b601e39f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bb5b2c4dc13c792fc9dc909e1a4e7593dff9978f152a62d834fbe273a0166ac7e659004f299d3d8ab5e5cc9464d7d11c5fa88f1c8d3c4bac2b1661a4f344563
|
7
|
+
data.tar.gz: c9ed11ba64c5de00b3dc248935c9345873741c071e7517f321b6c928b103bc52a9a59c69f65cf4e110d616c12257642c496e25a987501ab80a898b7231d8b774
|
@@ -6,7 +6,12 @@ module BulkDependencyEraser
|
|
6
6
|
# Some associations scopes take parameters.
|
7
7
|
# - We would have to instantiate if we wanted to apply that scope filter.
|
8
8
|
instantiate_if_assoc_scope_with_arity: false,
|
9
|
+
# wraps around the DB reading
|
9
10
|
db_read_wrapper: self::DEFAULT_DB_WRAPPER,
|
11
|
+
# Will parse these tables and their dependencies, but will remove the tables from the lists after parsing.
|
12
|
+
ignore_tables: [],
|
13
|
+
# Won't parse any table in this list
|
14
|
+
ignore_tables_and_dependencies: [],
|
10
15
|
}.freeze
|
11
16
|
|
12
17
|
DEPENDENCY_NULLIFY = %i[
|
@@ -36,17 +41,40 @@ module BulkDependencyEraser
|
|
36
41
|
].freeze
|
37
42
|
|
38
43
|
attr_reader :deletion_list, :nullification_list
|
44
|
+
attr_reader :ignore_table_deletion_list, :ignore_table_nullification_list
|
39
45
|
|
40
46
|
def initialize query:, opts: {}
|
41
47
|
@query = query
|
42
48
|
@deletion_list = {}
|
43
49
|
@nullification_list = {}
|
50
|
+
|
51
|
+
# For any ignored table results, they will be stored here
|
52
|
+
@ignore_table_deletion_list = {}
|
53
|
+
@ignore_table_nullification_list = {}
|
54
|
+
|
44
55
|
super(opts:)
|
56
|
+
|
57
|
+
# populate with klass_names for ignorable klasses
|
58
|
+
@ignore_klass_and_dependencies = opts_c.ignore_tables_and_dependencies.collect { |table_name| table_name.classify }
|
45
59
|
end
|
46
60
|
|
47
61
|
def execute
|
62
|
+
# go through deletion/nullification lists and remove any tables from 'ignore_tables' option
|
63
|
+
build_result = build
|
64
|
+
|
65
|
+
# move any klass names if told to ignore them into their respective new lists
|
66
|
+
opts_c.ignore_tables.each do |table_name|
|
67
|
+
klass_name = table_name.classify
|
68
|
+
ignore_table_deletion_list[klass_name] = deletion_list.delete(klass_name) if deletion_list.key?(klass_name)
|
69
|
+
ignore_table_nullification_list[klass_name] = nullification_list.delete(klass_name) if nullification_list.key?(klass_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
return build_result
|
73
|
+
end
|
74
|
+
|
75
|
+
def build
|
48
76
|
begin
|
49
|
-
|
77
|
+
deletion_query_parser(@query)
|
50
78
|
|
51
79
|
uniqify_errors!
|
52
80
|
|
@@ -88,6 +116,11 @@ module BulkDependencyEraser
|
|
88
116
|
table_klass_name = query.table_name.classify
|
89
117
|
end
|
90
118
|
|
119
|
+
if ignore_klass_and_dependencies.include?(table_klass_name)
|
120
|
+
# Not parsing, table and dependencies ignorable
|
121
|
+
return
|
122
|
+
end
|
123
|
+
|
91
124
|
if opts_c.verbose
|
92
125
|
if association_parent
|
93
126
|
puts "Building #{klass_name}"
|
@@ -247,7 +280,7 @@ module BulkDependencyEraser
|
|
247
280
|
deletion_query_parser(assoc_query, parent_class)
|
248
281
|
elsif type == :nullify
|
249
282
|
# No need for recursion here.
|
250
|
-
# - we're not destroying these assocs so we don't need to parse their dependencies.
|
283
|
+
# - we're not destroying these assocs (just nullifying foreign_key columns) so we don't need to parse their dependencies.
|
251
284
|
assoc_ids = read_from_db do
|
252
285
|
assoc_query.pluck(:id)
|
253
286
|
end
|
@@ -255,7 +288,6 @@ module BulkDependencyEraser
|
|
255
288
|
# No assoc_ids, no need to add it to the nullification list
|
256
289
|
return if assoc_ids.none?
|
257
290
|
|
258
|
-
# puts "FOUND IDS: #{assoc_ids.insect}"
|
259
291
|
nullification_list[assoc_table_klass_name] ||= {}
|
260
292
|
nullification_list[assoc_table_klass_name][specified_foreign_key] ||= []
|
261
293
|
nullification_list[assoc_table_klass_name][specified_foreign_key] += assoc_ids
|
@@ -267,6 +299,8 @@ module BulkDependencyEraser
|
|
267
299
|
|
268
300
|
protected
|
269
301
|
|
302
|
+
attr_reader :ignore_klass_and_dependencies
|
303
|
+
|
270
304
|
# A dependent assoc may be through another association. Follow the throughs to find the correct assoc to destroy.
|
271
305
|
def find_root_association_from_through_assocs klass, association_name
|
272
306
|
reflection = klass.reflect_on_association(association_name)
|
@@ -3,6 +3,8 @@ module BulkDependencyEraser
|
|
3
3
|
DEFAULT_OPTS = {
|
4
4
|
verbose: false,
|
5
5
|
db_delete_wrapper: self::DEFAULT_DB_WRAPPER,
|
6
|
+
# Set to true if you want 'ActiveRecord::InvalidForeignKey' errors raised during deletions
|
7
|
+
enable_invalid_foreign_key_detection: false
|
6
8
|
}.freeze
|
7
9
|
|
8
10
|
def initialize class_names_and_ids: {}, opts: {}
|
@@ -11,6 +13,10 @@ module BulkDependencyEraser
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def execute
|
16
|
+
if opts_c.verbose && opts_c.enable_invalid_foreign_key_detection
|
17
|
+
puts "ActiveRecord::Base.connection.disable_referential_integrity - disabled!"
|
18
|
+
end
|
19
|
+
|
14
20
|
ActiveRecord::Base.transaction do
|
15
21
|
current_class_name = 'N/A'
|
16
22
|
begin
|
@@ -19,12 +25,16 @@ module BulkDependencyEraser
|
|
19
25
|
ids = class_names_and_ids[class_name]
|
20
26
|
klass = class_name.constantize
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
if opts_c.enable_invalid_foreign_key_detection
|
29
|
+
# delete with referential integrity
|
30
|
+
delete_by_klass_and_ids(klass, ids)
|
31
|
+
else
|
32
|
+
# delete without referential integrity
|
33
|
+
# Disable any ActiveRecord::InvalidForeignKey raised errors.
|
34
|
+
# - src: https://stackoverflow.com/questions/41005849/rails-migrations-temporarily-ignore-foreign-key-constraint
|
35
|
+
# https://apidock.com/rails/ActiveRecord/ConnectionAdapters/AbstractAdapter/disable_referential_integrity
|
36
|
+
ActiveRecord::Base.connection.disable_referential_integrity do
|
37
|
+
delete_by_klass_and_ids(klass, ids)
|
28
38
|
end
|
29
39
|
end
|
30
40
|
end
|
@@ -39,6 +49,13 @@ module BulkDependencyEraser
|
|
39
49
|
|
40
50
|
protected
|
41
51
|
|
52
|
+
def delete_by_klass_and_ids klass, ids
|
53
|
+
puts "Deleting #{klass.name}'s IDs: #{ids}" if opts_c.verbose
|
54
|
+
delete_in_db do
|
55
|
+
klass.unscoped.where(id: ids).delete_all
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
42
59
|
attr_reader :class_names_and_ids
|
43
60
|
|
44
61
|
def delete_in_db(&block)
|
@@ -5,6 +5,7 @@ module BulkDependencyEraser
|
|
5
5
|
}.freeze
|
6
6
|
|
7
7
|
delegate :nullification_list, :deletion_list, to: :dependency_builder
|
8
|
+
delegate :ignore_table_deletion_list, :ignore_table_nullification_list, to: :dependency_builder
|
8
9
|
|
9
10
|
# @param query [ActiveRecord::Base | ActiveRecord::Relation]
|
10
11
|
def initialize query:, opts: {}
|
@@ -62,7 +63,6 @@ module BulkDependencyEraser
|
|
62
63
|
unless nullifier_execution
|
63
64
|
puts "Nullifier execution FAILED" if opts_c.verbose
|
64
65
|
merge_errors(nullifier.errors, 'Nullifier: ')
|
65
|
-
@errors += nullifier.errors
|
66
66
|
else
|
67
67
|
puts "Nullifier execution SUCCESSFUL" if opts_c.verbose
|
68
68
|
end
|