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: 29a1a21db1dd7be9228776c4dd8c0f62fe53e626292fdc3423a60659ffe6bfbb
4
- data.tar.gz: f1d447a7c617b90061ad3f836074449fed01d0bbf3fd2f98f1f6f50b027fb23b
3
+ metadata.gz: e9acdcdfc546fa1f49d03d2f52f785e8a012211cb2fead2ff5dad11767d125cc
4
+ data.tar.gz: e46db80ef699f7ad8a8ffbd4f9689f15c019826ad65acdbbd1d982cdaa423a52
5
5
  SHA512:
6
- metadata.gz: 4d4ca0d71e2f5f4916dedbf510478e3cd3b431f48116ff83479fa7f3502e2e5c0878833348827eb5f873f7c617c50095281abe72c936cbb6189c28ee67a7aa0c
7
- data.tar.gz: 16f5c31e7c3971094b98bf90ae3a9d40fc276a3b5abd5d29502484978143e2fdb0b05c635fe75aea604c42476ed191f1e809be3f9d2c25f289c6154cbfcb2555
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
+ ```
@@ -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::class
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] = ids
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| ![:destroy, 'destroy'].include?(v.options&.dig(:dependent)) }.collect{ |v| v.name }
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.reverse.each do |class_name|
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 << [klass, ids]
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 |klass, ids|
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.2"
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.}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_delete_all_and_assocs_without_instantiation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - benjamin.dana.software.dev@gmail.com