delete_recursively 0.9.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/delete_recursively.rb +134 -84
  3. metadata +40 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60b6a4cc1cae62c705d0af8656a789f8839d5356
4
- data.tar.gz: 408e3ff5f591eae523ca8d4b891e96f507323164
3
+ metadata.gz: bc815c840d3f1514a41c2254278aa84205aa1b29
4
+ data.tar.gz: 144a4055f89143dbd6e3744839fa7fe4897c6300
5
5
  SHA512:
6
- metadata.gz: fb4fe70e5eb85725fc696521c15d154250606a73f3104016995534c9b3610a2b6a387de67a695f73c8bbf9fd3cc9157d6572b7e576111ab1a02db00e54b79bae
7
- data.tar.gz: 307924de1047c286cca034584b348954d4b90b8a4261a0fbb2e7ba6ef0dc841e8ef748750e42d66b81b565e6ad32e93ebc1830ffb750cff24daac1f6310661f2
6
+ metadata.gz: 91b7bc103274442ad9e424e4058b9bd7b66e460f98146ef0110e63bb6764e3f1b43fa0668ee7b017a5a3072840ca880e235f1f48324353ac2aecd7f5be440c7c
7
+ data.tar.gz: b07cbf652da91fcc0fe961affb61edef238097456c5fcc63cba249474b977e9631e62d93f9e5bc0e80637b798a01eb894d799f2520880ef7a61f6dd12bd1348d
@@ -1,84 +1,134 @@
1
- #
2
- # DeleteRecursively
3
- #
4
- # Adds a new dependent: option to ActiveRecord associations.
5
- #
6
- module DeleteRecursively
7
- NEW_DEPENDENT_OPTION = :delete_recursively
8
-
9
- # override ::valid_dependent_options to make the new
10
- # dependent option available to Association::Builder classes
11
- module OptionPermission
12
- def valid_dependent_options
13
- super + [NEW_DEPENDENT_OPTION]
14
- end
15
- end
16
-
17
- # override Association#handle_dependency to apply the new option if it is set
18
- module DependencyHandling
19
- def handle_dependency
20
- return super unless DeleteRecursively.enabled_for?(self)
21
- if reflection.belongs_to?
22
- # can't use ::dependent_ids, owner is already destroyed at this point
23
- ids = load_target ? target.id : []
24
- else
25
- ids = DeleteRecursively.dependent_ids(owner.class, owner.id, reflection)
26
- end
27
- DeleteRecursively.delete_recursively(reflection, ids)
28
- end
29
- end
30
-
31
- def self.delete_recursively(reflection, record_ids)
32
- record_class = reflection.klass
33
- record_class.reflect_on_all_associations.each do |sub_reflection|
34
- next unless recurse_on?(sub_reflection)
35
- dependent_ids = dependent_ids(record_class, record_ids, sub_reflection)
36
- delete_recursively(sub_reflection, dependent_ids)
37
- end
38
- record_class.delete(record_ids) if enabled_for?(reflection)
39
- record_class.destroy(record_ids) if destructive?(reflection)
40
- end
41
-
42
- def self.recurse_on?(reflection)
43
- enabled_for?(reflection) || destructive?(reflection)
44
- end
45
-
46
- def self.enabled_for?(reflection)
47
- reflection.options[:dependent] == NEW_DEPENDENT_OPTION
48
- end
49
-
50
- def self.destructive?(reflection)
51
- [:destroy, :destroy_all].include?(reflection.options[:dependent])
52
- end
53
-
54
- def self.dependent_ids(owner_class, owner_ids, reflection)
55
- if reflection.belongs_to?
56
- owners_arel = owner_class.where(owner_class.primary_key => owner_ids)
57
- owners_arel.pluck(reflection.association_foreign_key).compact
58
- else
59
- custom_foreign_key = reflection.options[:foreign_key]
60
- foreign_key = custom_foreign_key || owner_class.to_s.foreign_key
61
- reflection.klass.where(foreign_key => owner_ids).ids
62
- end
63
- end
64
-
65
- def self.all(record_class, criteria = {})
66
- applicable_criteria = criteria.select do |column_name, _value|
67
- record_class.column_names.include?(column_name.to_s)
68
- end
69
- record_class.where(applicable_criteria).delete_all
70
- record_class.reflect_on_all_associations.each do |reflection|
71
- all(reflection.klass, criteria) if recurse_on?(reflection)
72
- end
73
- end
74
- end
75
-
76
- require 'active_record'
77
-
78
- %w(BelongsTo HasMany HasOne).each do |assoc_name|
79
- assoc_builder = ActiveRecord::Associations::Builder.const_get(assoc_name)
80
- assoc_builder.singleton_class.prepend(DeleteRecursively::OptionPermission)
81
-
82
- assoc_class = ActiveRecord::Associations.const_get("#{assoc_name}Association")
83
- assoc_class.prepend(DeleteRecursively::DependencyHandling)
84
- end
1
+ #
2
+ # DeleteRecursively
3
+ #
4
+ # Adds a new dependent: option to ActiveRecord associations.
5
+ #
6
+ module DeleteRecursively
7
+ require_relative File.join('delete_recursively', 'version')
8
+
9
+ NEW_DEPENDENT_OPTION = :delete_recursively
10
+
11
+ # override ::valid_dependent_options to make the new
12
+ # dependent option available to Association::Builder classes
13
+ module OptionPermission
14
+ def valid_dependent_options
15
+ super + [NEW_DEPENDENT_OPTION]
16
+ end
17
+ end
18
+
19
+ # override Association#handle_dependency to apply the new option if it is set
20
+ module DependencyHandling
21
+ def handle_dependency
22
+ return super unless DeleteRecursively.enabled_for?(self)
23
+ if reflection.belongs_to?
24
+ # can't use ::dependent_ids, owner is already destroyed at this point
25
+ ids = load_target ? target.id : []
26
+ else
27
+ ids = DeleteRecursively.dependent_ids(owner.class, owner.id, reflection)
28
+ end
29
+ DeleteRecursively.delete_recursively(reflection, ids)
30
+ end
31
+ end
32
+
33
+ class << self
34
+ def delete_recursively(reflection, record_ids)
35
+ record_class = reflection.klass
36
+ if recurse_on?(reflection)
37
+ record_class.reflect_on_all_associations.each do |sub_reflection|
38
+ dependent_ids = dependent_ids(record_class, record_ids, sub_reflection)
39
+ delete_recursively(sub_reflection, dependent_ids)
40
+ end
41
+ end
42
+ destroy_or_delete(reflection, record_class, record_ids)
43
+ end
44
+
45
+ def destroy_or_delete(reflection, record_class, record_ids)
46
+ if destructive?(reflection)
47
+ record_class.destroy(record_ids)
48
+ elsif enabled_for?(reflection) || deleting?(reflection)
49
+ record_class.delete(record_ids)
50
+ end
51
+ end
52
+
53
+ def recurse_on?(reflection)
54
+ enabled_for?(reflection) || destructive?(reflection)
55
+ end
56
+
57
+ def enabled_for?(reflection)
58
+ reflection.options[:dependent] == NEW_DEPENDENT_OPTION
59
+ end
60
+
61
+ def destructive?(reflection)
62
+ [:destroy, :destroy_all].include?(reflection.options[:dependent])
63
+ end
64
+
65
+ def deleting?(reflection)
66
+ [:delete, :delete_all].include?(reflection.options[:dependent])
67
+ end
68
+
69
+ def dependent_ids(owner_class, owner_ids, reflection)
70
+ if reflection.belongs_to?
71
+ owners_arel = owner_class.where(owner_class.primary_key => owner_ids)
72
+ owners_arel.pluck(reflection.association_foreign_key).compact
73
+ elsif reflection.through_reflection
74
+ dependent_ids_with_through_option(owner_class, owner_ids, reflection)
75
+ else
76
+ owner_foreign_key = foreign_key(owner_class, reflection)
77
+ reflection.klass.where(owner_foreign_key => owner_ids).ids
78
+ end
79
+ end
80
+
81
+ def dependent_ids_with_through_option(owner_class, owner_ids, reflection)
82
+ through_reflection = reflection.through_reflection
83
+ owner_foreign_key = foreign_key(owner_class, through_reflection)
84
+
85
+ dependent_class = reflection.klass
86
+ dependent_through_reflection = inverse_through_reflection(reflection)
87
+ dependent_foreign_key =
88
+ foreign_key(dependent_class, dependent_through_reflection)
89
+
90
+ through_reflection.klass
91
+ .where(owner_foreign_key => owner_ids).pluck(dependent_foreign_key)
92
+ end
93
+
94
+ def inverse_through_reflection(reflection)
95
+ through_class = reflection.through_reflection.klass
96
+ reflection.klass.reflect_on_all_associations
97
+ .map(&:through_reflection)
98
+ .find { |tr| tr && tr.klass == through_class }
99
+ end
100
+
101
+ def foreign_key(owner_class, reflection)
102
+ custom_foreign_key = reflection && reflection.options[:foreign_key]
103
+ custom_foreign_key || owner_class.to_s.foreign_key
104
+ end
105
+
106
+ def all(record_class, criteria = {})
107
+ record_class.reflect_on_all_associations.each do |reflection|
108
+ if recurse_on?(reflection)
109
+ all(reflection.klass, criteria)
110
+ elsif deleting?(reflection)
111
+ delete_with_applicable_criteria(reflection.klass, criteria)
112
+ end
113
+ end
114
+ delete_with_applicable_criteria(record_class, criteria)
115
+ end
116
+
117
+ def delete_with_applicable_criteria(record_class, criteria)
118
+ applicable_criteria = criteria.select do |column_name, _value|
119
+ record_class.column_names.include?(column_name.to_s)
120
+ end
121
+ record_class.where(applicable_criteria).delete_all
122
+ end
123
+ end
124
+ end
125
+
126
+ require 'active_record'
127
+
128
+ %w(BelongsTo HasMany HasOne).each do |assoc_name|
129
+ assoc_builder = ActiveRecord::Associations::Builder.const_get(assoc_name)
130
+ assoc_builder.singleton_class.prepend(DeleteRecursively::OptionPermission)
131
+
132
+ assoc_class = ActiveRecord::Associations.const_get("#{assoc_name}Association")
133
+ assoc_class.prepend(DeleteRecursively::DependencyHandling)
134
+ end
metadata CHANGED
@@ -1,71 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delete_recursively
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janosch Müller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-05 00:00:00.000000000 Z
11
+ date: 2017-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.14
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: '5.0'
22
+ version: 6.0.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 4.1.14
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 6.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: appraisal
35
+ requirement: !ruby/object:Gem::Requirement
23
36
  requirements:
24
37
  - - "~>"
25
38
  - !ruby/object:Gem::Version
26
- version: '5.0'
39
+ version: '2.2'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.2'
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: codeclimate-test-reporter
29
49
  requirement: !ruby/object:Gem::Requirement
30
50
  requirements:
31
51
  - - "~>"
32
52
  - !ruby/object:Gem::Version
33
- version: '0.6'
53
+ version: '1.0'
34
54
  type: :development
35
55
  prerelease: false
36
56
  version_requirements: !ruby/object:Gem::Requirement
37
57
  requirements:
38
58
  - - "~>"
39
59
  - !ruby/object:Gem::Version
40
- version: '0.6'
60
+ version: '1.0'
41
61
  - !ruby/object:Gem::Dependency
42
62
  name: rails
43
63
  requirement: !ruby/object:Gem::Requirement
44
64
  requirements:
45
- - - "~>"
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 4.1.14
68
+ - - "<"
46
69
  - !ruby/object:Gem::Version
47
- version: '5.0'
70
+ version: 6.0.0
48
71
  type: :development
49
72
  prerelease: false
50
73
  version_requirements: !ruby/object:Gem::Requirement
51
74
  requirements:
52
- - - "~>"
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 4.1.14
78
+ - - "<"
53
79
  - !ruby/object:Gem::Version
54
- version: '5.0'
80
+ version: 6.0.0
55
81
  - !ruby/object:Gem::Dependency
56
82
  name: rake
57
83
  requirement: !ruby/object:Gem::Requirement
58
84
  requirements:
59
85
  - - "~>"
60
86
  - !ruby/object:Gem::Version
61
- version: '11.2'
87
+ version: '11.3'
62
88
  type: :development
63
89
  prerelease: false
64
90
  version_requirements: !ruby/object:Gem::Requirement
65
91
  requirements:
66
92
  - - "~>"
67
93
  - !ruby/object:Gem::Version
68
- version: '11.2'
94
+ version: '11.3'
69
95
  - !ruby/object:Gem::Dependency
70
96
  name: rspec
71
97
  requirement: !ruby/object:Gem::Requirement
@@ -136,9 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
162
  version: '0'
137
163
  requirements: []
138
164
  rubyforge_project:
139
- rubygems_version: 2.4.8
165
+ rubygems_version: 2.6.11
140
166
  signing_key:
141
167
  specification_version: 4
142
168
  summary: Delete ActiveRecords efficiently
143
169
  test_files: []
144
- has_rdoc: