rails_delete_all_and_assocs_without_instantiation 0.0.2 → 0.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: e9acdcdfc546fa1f49d03d2f52f785e8a012211cb2fead2ff5dad11767d125cc
|
4
|
+
data.tar.gz: e46db80ef699f7ad8a8ffbd4f9689f15c019826ad65acdbbd1d982cdaa423a52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87cdde62744d43c2567d6b55a59ccddcd0a412925c6d396294396839d12036dab633d3a3fd09d3284952bd5a351d4467c27d0426e5cf088b92b83963860f284c
|
7
|
+
data.tar.gz: 19ac4b45404cd36e02d1f1aac7cf8a9598a862ae272e32553258a377dbf2af8aa28ffc7047aa6e817898ab32fbb8922180b4b48bd5009d4243365fbb30187354
|
data/README.md
CHANGED
@@ -36,3 +36,22 @@ class User < ApplicationRecord
|
|
36
36
|
has_many :creator_accounts, -> (user_id) { where(creator_id: user_id) }, dependent: :destroy
|
37
37
|
end
|
38
38
|
```
|
39
|
+
|
40
|
+
# Customization
|
41
|
+
```
|
42
|
+
class User
|
43
|
+
# This is a way you can do more advanced filtering on association dependencies, and not just wipe everything
|
44
|
+
def self.delete_all_and_assocs_without_instantiation_builder models_and_ids_list = {}, errors = [], options = {}
|
45
|
+
original_account_ids = models_and_ids_list['Account']
|
46
|
+
models_and_ids_list, errors = super(models_and_ids_list, errors, options)
|
47
|
+
# we've ignored the deletion command that may or may not have been created by your assoc definition
|
48
|
+
models_and_ids_list['Account'] = original_account_ids
|
49
|
+
|
50
|
+
query = self.where({}).includes(:accounts).joins(:accounts).where(accounts: {marketable: true})
|
51
|
+
account_ids = query.collect{|pro| pro.accounts.map(&:id) }.flatten
|
52
|
+
models_and_ids_list, errors = Account.unscoped.where(id: account_ids).delete_all_and_assocs_without_instantiation_builder(models_and_ids_list, errors, options)
|
53
|
+
|
54
|
+
return models_and_ids_list, errors
|
55
|
+
end
|
56
|
+
end
|
57
|
+
```
|
data/lib/rails_delete_all_and_assocs_without_instantiation/delete_all_and_assocs_extension.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
module RailsDeleteAllAndAssocsWithoutInstantiation
|
2
2
|
module DeleteAllAndAssocsWithoutInstantiation
|
3
|
+
MATCH_DEPENDENT_ASSOC_VALUE = [
|
4
|
+
:destroy,
|
5
|
+
'destroy',
|
6
|
+
:delete_all,
|
7
|
+
'delete_all',
|
8
|
+
:destroy_async,
|
9
|
+
'destroy_async',
|
10
|
+
]
|
3
11
|
|
4
12
|
# rails interpretation is different than expected:
|
5
13
|
# https://makandracards.com/makandra/32175-don-t-forget-automatically-remove-join-records-on-has_many-through-associations
|
@@ -22,25 +30,25 @@ module RailsDeleteAllAndAssocsWithoutInstantiation
|
|
22
30
|
# force_through_destroy_chains = options[:force_destroy_chain] || {}
|
23
31
|
# do_not_destroy_self = options[:do_not_destroy] || {}
|
24
32
|
|
25
|
-
current_class = self
|
33
|
+
current_class = self.name
|
26
34
|
current_query = self
|
27
35
|
ids = current_query.pluck(:id)
|
28
36
|
models_and_ids_list[name] ||= []
|
29
37
|
|
30
38
|
# prevent infinite recursion here.
|
31
39
|
ids = ids - models_and_ids_list[self.name]
|
32
|
-
if ids.none?
|
40
|
+
if ids.none? || ids.nil?
|
33
41
|
return models_and_ids_list, errors
|
34
42
|
end
|
35
43
|
|
36
|
-
models_and_ids_list[self.name]
|
44
|
+
models_and_ids_list[self.name] += ids
|
37
45
|
|
38
46
|
# if do_not_destroy_self != true
|
39
47
|
# models_and_ids_list[name] += ids
|
40
48
|
# end
|
41
49
|
|
42
50
|
# ignore associations that aren't dependent destroyable.
|
43
|
-
destroy_association_names = self.reflect_on_all_associations.reject{|v| !
|
51
|
+
destroy_association_names = self.reflect_on_all_associations.reject{|v| !MATCH_DEPENDENT_ASSOC_VALUE.include?(v.options&.dig(:dependent)) }.collect{ |v| v.name }
|
44
52
|
|
45
53
|
|
46
54
|
# associations that we might not necessarilly need to delete, but need to go through
|
@@ -145,24 +153,38 @@ module RailsDeleteAllAndAssocsWithoutInstantiation
|
|
145
153
|
retry_due_to_errors = []
|
146
154
|
retry_to_capture_errors = []
|
147
155
|
|
156
|
+
if options[:verbose]
|
157
|
+
puts "DELETION STRUCTURE"
|
158
|
+
puts built_deletions.inspect
|
159
|
+
end
|
160
|
+
|
148
161
|
ActiveRecord::Base.transaction do
|
149
162
|
built_deletions.keys.reverse.each do |class_name|
|
163
|
+
ids = "N/A"
|
150
164
|
begin
|
151
165
|
ids = built_deletions[class_name]
|
152
|
-
next if ids.none?
|
166
|
+
next if ids.none? || ids.nil?
|
153
167
|
klass = class_name.constantize
|
154
168
|
klass.unscoped.where(id: ids).delete_all
|
155
169
|
rescue Exception => e
|
170
|
+
puts "DEL ATTEMPT 1: #{class_name}.unscoped.where(id: #{ids}).delete_all" if options[:verbose]
|
156
171
|
retry_due_to_errors << class_name
|
157
172
|
end
|
158
173
|
end
|
159
174
|
|
175
|
+
if options[:verbose]
|
176
|
+
puts "RETRY DUE TO ERRORS:"
|
177
|
+
puts retry_due_to_errors.inspect
|
178
|
+
end
|
179
|
+
|
160
180
|
# ActiveRecord::InvalidForeignKey can cause issues in ordering.
|
161
|
-
retry_due_to_errors.
|
181
|
+
retry_due_to_errors.each do |class_name|
|
182
|
+
ids = "N/A"
|
162
183
|
begin
|
163
184
|
ids = built_deletions[class_name]
|
164
|
-
next if ids.none?
|
185
|
+
next if ids.none? || ids.nil?
|
165
186
|
klass = class_name.constantize
|
187
|
+
puts "DEL ATTEMPT 2: #{class_name}.unscoped.where(id: #{ids}).delete_all" if options[:verbose]
|
166
188
|
klass.unscoped.where(id: ids).delete_all
|
167
189
|
# if Rails.env.test? || Rails.env.development?
|
168
190
|
# if count = klass.unscoped.where(id: ids).count > 0
|
@@ -172,20 +194,27 @@ module RailsDeleteAllAndAssocsWithoutInstantiation
|
|
172
194
|
rescue Exception => e
|
173
195
|
# ActiveRecord::Base.transaction obscures the actual errors
|
174
196
|
# - need to run again outside of block to get actual error
|
175
|
-
retry_to_capture_errors << [
|
197
|
+
retry_to_capture_errors << [class_name, ids]
|
176
198
|
raise ActiveRecord::Rollback
|
177
199
|
end
|
178
200
|
end
|
179
201
|
end
|
180
202
|
|
181
|
-
retry_to_capture_errors.each do |
|
203
|
+
retry_to_capture_errors.each do |class_name, ids|
|
204
|
+
if ids == "N/A"
|
205
|
+
errors << ["Internal Server Error, could not locate IDs", class_name]
|
206
|
+
next
|
207
|
+
end
|
182
208
|
begin
|
209
|
+
klass = class_name.constantize
|
210
|
+
puts "DEL ATTEMPT 3: #{class_name}.unscoped.where(id: #{ids}).delete_all" if options[:verbose]
|
183
211
|
klass.unscoped.where(id: ids).delete_all
|
184
212
|
# should never get past this line, we're expecting an error!
|
185
213
|
# - if we do, maybe was an intermittent issue. Call ourselves recursively to try again.
|
186
|
-
return current_query.delete_all_and_assocs_without_instantiation(options)
|
214
|
+
# return current_query.delete_all_and_assocs_without_instantiation(options)
|
215
|
+
errors << ["#{class_name} - expected error, ran into 2 errors on previous deletion attempts", ids]
|
187
216
|
rescue Exception => e
|
188
|
-
errors << e.class.to_s + "; " + e.message
|
217
|
+
errors << [e.class.to_s + "; " + e.message, e.backtrace]
|
189
218
|
end
|
190
219
|
|
191
220
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rails_delete_all_and_assocs_without_instantiation}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.4"
|
6
6
|
s.date = %q{2023-03-02}
|
7
7
|
s.authors = ["benjamin.dana.software.dev@gmail.com"]
|
8
8
|
s.summary = %q{Non-instantiated way of deleting records with dependencies quickly without instantiation.}
|