delete_recursively 0.9.4 → 1.0.0

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.
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: