cascade-deleter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6a0e10f1734aed0dcc89834897e051c0e26bbf463706843f60fa90564e90188a
4
+ data.tar.gz: 46fdd8434d43e0ab32c92cfcff66047988023c2494f00e47eff5ea5b87512e7e
5
+ SHA512:
6
+ metadata.gz: 7dd2d5bb3669bd742fe76fecf44ff5236b47e43c27cddfeaf7cf675ac85f1a8ca0b2dd3d2d1523451c9e08cc43e489502fa06d04e079441b28a67b4c76456c36
7
+ data.tar.gz: 7697d23ef95f3661b30a82c29f22882e02d2fdf4c3bdbad12befb8c99255b976c0f8f1d1a1c4e9b1e625a21bac862f80ac12d3a873b83888d5c4efd5a691da00
@@ -0,0 +1,77 @@
1
+ require 'hierarchy_tree'
2
+ require 'deactivator'
3
+
4
+ # Cascade delete items and all of their children items
5
+ # ⚠ Be aware, this lib executes HARD deletions, so
6
+ # 1. The items will be completely removed from the database
7
+ # 2. No validations or callbacks will be triggered
8
+ # Usage 1: CascadeDeleter.new(Project.unscoped.where(active: false)).delete_all
9
+ # Usage 2: CascadeDeleter.new(Project.unscoped.where(active: false)).delete_all(
10
+ # custom_joins: { 'Attachment' => {:subproject=>:project} }
11
+ # )
12
+ # Usage 3: CascadeDeleter.new(Discipline.where_like(description: '[TO BE DELETED]')).delete_all(
13
+ # method: :soft
14
+ # )
15
+
16
+ ################ Debug ################
17
+ # gem cleanup cascade-deleter
18
+ # rm cascade-deleter-0.1.0.gem
19
+ # gem build cascade_deleter
20
+ # gem install cascade-deleter-0.1.0.gem
21
+ # ruby -Itest test/test_cascade_deleter.rb
22
+ class CascadeDeleter
23
+ def initialize(items)
24
+ @items = items
25
+ @class = @items.klass
26
+ @classes = classes
27
+ end
28
+
29
+ def delete_all(custom_joins: {}, method: :hard)
30
+ Deactivator.new(@classes).without_default_scopes do
31
+ ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS = 0;')
32
+
33
+ ActiveRecord::Base.transaction do
34
+ @classes.map(&:constantize).each do |klass|
35
+ delete(klass, build_join(klass, custom_joins), method)
36
+ end
37
+ end
38
+ ensure
39
+ ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS = 1;')
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def classes
46
+ Hierarchy.bottom_up_classes(@class).without('Audited::Audit')
47
+ end
48
+
49
+ def delete(klass, join, method)
50
+ puts "#{method.to_s.titleize} Deleting #{klass.name.pluralize.titleize}".green
51
+ count = apply_delete(build_query(klass, join), method)
52
+ puts "#{count} #{klass.name.pluralize.titleize} are #{method} deleted".yellow
53
+ end
54
+
55
+ def apply_delete(items, method)
56
+ case method
57
+ when :hard
58
+ items.delete_all
59
+ when :soft
60
+ items.update_all(active: false, updated_at: Time.now)
61
+ else
62
+ puts 'Unregistered Delete Method. Possible methods → :hard or :soft'.red
63
+ 0
64
+ end
65
+ end
66
+
67
+ def build_query(klass, join)
68
+ return @items if @class.to_s == klass.to_s
69
+
70
+ klass.joins(join).where(@class.table_name => { id: @items.select(:id) })
71
+ end
72
+
73
+ def build_join(model, custom_joins = {})
74
+ custom_joins[model.to_s] || Hierarchy.ancestors_bfs(from: model, to: @class)
75
+ # You can use `Hierarchy.ancestors(from: model, to: @class)` to choose one custom_join
76
+ end
77
+ end
@@ -0,0 +1,45 @@
1
+ # Deactivate default_scopes for the given classes for a given code block
2
+ # --------------------------- Usage ---------------------------
3
+ # Deactivator.new(['ClassA', 'ClassB']).without_default_scopes do
4
+ # My
5
+ # Code
6
+ # Block
7
+ # Without ClassA and ClassB default_scopes
8
+ # end
9
+ class Deactivator
10
+ def initialize(classes)
11
+ @classes = classes
12
+ @default_scopes = capture_default_scopes
13
+ end
14
+
15
+ def without_default_scopes
16
+ remove_default_scopes
17
+ yield
18
+ ensure
19
+ restore_default_scopes
20
+ end
21
+
22
+ private
23
+
24
+ def capture_default_scopes
25
+ @classes.to_h do |klass|
26
+ [klass, klass.constantize.default_scopes]
27
+ end
28
+ end
29
+
30
+ def remove_default_scopes
31
+ @classes.each do |klass|
32
+ klass.constantize.class_eval { self.default_scopes = [] }
33
+ end
34
+ end
35
+
36
+ def restore_default_scopes
37
+ deactivator = self
38
+
39
+ @classes.each do |klass|
40
+ klass.constantize.class_eval do
41
+ self.default_scopes = deactivator.instance_variable_get(:@default_scopes)[klass]
42
+ end
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cascade-deleter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Victor Cordeiro Costa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hierarchy-tree
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.3.5
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.3.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.1'
55
+ description: |-
56
+ cascade-deleter is a ruby gem designed to delete items
57
+ with all of their descendant items in their hierarchy.
58
+ email:
59
+ - victorcorcos@gmail.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - lib/cascade_deleter.rb
65
+ - lib/deactivator.rb
66
+ homepage: https://github.com/Victorcorcos/cascade-deleter
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '2.0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubygems_version: 3.1.6
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: cascade-deleter is a ruby gem designed to delete items with all of their
89
+ descendant items in their hierarchy.
90
+ test_files: []