dependency-trees 0.0.4 → 0.0.5
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 +4 -4
- data/dependency-trees-0.0.3.gem +0 -0
- data/dependency-trees-0.0.4.gem +0 -0
- data/dependency-trees.gemspec +1 -1
- data/lib/dependency-trees.rb +5 -1
- data/lib/dependency_tree.rb +144 -0
- data/lib/ids_of_all_dependencies.rb +4 -201
- data/lib/ids_of_all_dependencies_nested.rb +26 -0
- data/lib/ids_of_all_direct_dependencies.rb +18 -0
- data/lib/nullify_dependencies.rb +50 -0
- metadata +7 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7bece88844a0b550c9d20a760c4117baf3855b23691d6cf2587b93826468ed4
|
4
|
+
data.tar.gz: 16a7a5f35a91a69189e84f89a00bb48c9f60fc1ca22ac5ab54b33086c3b19b89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c22a3aca65a95892ee610ed02a8675b7f80eb04da6f2983e2fce6f4eb9c4acc61e91da06d14ebe5d8448fd377ffe92204fe9bb6f73db637c5874aec8fc2b0632
|
7
|
+
data.tar.gz: c4f58e0936b57cc19f286f3f43fd70c5be86eed731ef08b498abd88a4f523ab3763172393ad77f2ab4e279e7570fbf12e87f76d0d3c7250be02d488fc42bd0a1
|
Binary file
|
Binary file
|
data/dependency-trees.gemspec
CHANGED
data/lib/dependency-trees.rb
CHANGED
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'id_hash'
|
2
|
+
|
3
|
+
module DependencyTree
|
4
|
+
class Tree < Hash
|
5
|
+
def initialize(hash={})
|
6
|
+
hash.each do |key, value|
|
7
|
+
self[key] = value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def ids_tree
|
12
|
+
self_cloned = self.deep_tree_clone
|
13
|
+
self_cloned.delete_key_recursive(:instance)
|
14
|
+
end
|
15
|
+
|
16
|
+
def status_tree
|
17
|
+
self_cloned = self.deep_tree_clone
|
18
|
+
|
19
|
+
self_cloned.do_recursive do |tree|
|
20
|
+
begin
|
21
|
+
tree[:instance].reload
|
22
|
+
tree[:status] = 'present'
|
23
|
+
rescue ActiveRecord::RecordNotFound => e
|
24
|
+
tree[:status] = 'removed'
|
25
|
+
end
|
26
|
+
|
27
|
+
tree.delete(:instance)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def status_tree_condensed
|
32
|
+
result = status_tree.do_recursive do |tree|
|
33
|
+
tree.each do |name, array|
|
34
|
+
next unless array.class == Array
|
35
|
+
|
36
|
+
new_array = array.map do |subtree|
|
37
|
+
next subtree.root_duplicate_summary if subtree[:duplicate]
|
38
|
+
next subtree if subtree.class != Tree || subtree.size > 2
|
39
|
+
|
40
|
+
subtree.root_summary
|
41
|
+
end
|
42
|
+
|
43
|
+
array.clear
|
44
|
+
array.concat(new_array)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
result.do_recursive do |tree|
|
49
|
+
tree[:_] = tree.root_summary
|
50
|
+
tree.delete(:id)
|
51
|
+
tree.delete(:status)
|
52
|
+
tree.delete(:class)
|
53
|
+
tree.last_to_beginning!
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def last_to_beginning!
|
58
|
+
arr = self.to_a
|
59
|
+
arr.unshift(arr.pop)
|
60
|
+
self.clear
|
61
|
+
self.merge!(arr.to_h)
|
62
|
+
end
|
63
|
+
|
64
|
+
def root_summary
|
65
|
+
"#{self[:class]}, id #{self[:id]}, #{self[:status]}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def root_duplicate_summary
|
69
|
+
root_summary + ", duplicate"
|
70
|
+
end
|
71
|
+
|
72
|
+
def deep_tree_clone
|
73
|
+
hash = self.clone.map do |key, array|
|
74
|
+
next [key, array] unless array.class == Array
|
75
|
+
|
76
|
+
new_array = array.map do |subtree|
|
77
|
+
if subtree.class == Tree
|
78
|
+
subtree.deep_tree_clone
|
79
|
+
else
|
80
|
+
subtree
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
[key, new_array]
|
85
|
+
end
|
86
|
+
|
87
|
+
Tree.new(hash)
|
88
|
+
end
|
89
|
+
|
90
|
+
def delete_key_recursive(key)
|
91
|
+
call_method_recursive(:delete, key)
|
92
|
+
end
|
93
|
+
|
94
|
+
def call_method_recursive(method, *args, &block)
|
95
|
+
do_recursive do |tree|
|
96
|
+
tree.send(method, *args, &block)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def do_recursive(&block)
|
101
|
+
block.call(self)
|
102
|
+
|
103
|
+
self.each do |key, array|
|
104
|
+
next unless array.is_a? Array
|
105
|
+
|
106
|
+
array.each do |subtree|
|
107
|
+
subtree.do_recursive(&block) if subtree.is_a? Tree
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
self
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def dependency_tree(depth = Float::INFINITY, hash_for_duplication_check = IdHash.new)
|
116
|
+
is_duplicate = hash_for_duplication_check[self.class]&.include?(id)
|
117
|
+
hash_for_duplication_check.add(self.class, id)
|
118
|
+
shoud_go_deeper = depth > 0 && !is_duplicate
|
119
|
+
result = shoud_go_deeper ? get_associations_for_tree(depth, hash_for_duplication_check) : Tree.new
|
120
|
+
result[:id] = id
|
121
|
+
result[:instance] = self
|
122
|
+
result[:duplicate] = true if is_duplicate
|
123
|
+
result
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def get_associations_for_tree(depth, hash_for_duplication_check)
|
129
|
+
result = Tree.new
|
130
|
+
|
131
|
+
self.class.reflect_on_all_associations.map do |association|
|
132
|
+
next if association.macro == :belongs_to
|
133
|
+
|
134
|
+
symbol = association.name
|
135
|
+
self.send(association.name).sort_by(&:id).map do |associated_object|
|
136
|
+
result[symbol] = [] if result[symbol].nil?
|
137
|
+
result[symbol] << associated_object.dependency_tree(depth - 1, hash_for_duplication_check)
|
138
|
+
result[:class] = association.klass.name.underscore.to_sym
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
result
|
143
|
+
end
|
144
|
+
end
|
@@ -1,206 +1,9 @@
|
|
1
1
|
require 'id_hash'
|
2
2
|
|
3
|
-
module SymbolsOfAllDirectDependencies
|
4
|
-
def symbols_of_all_direct_dependencies
|
5
|
-
self.class.reflect_on_all_associations.map do |association|
|
6
|
-
next if association.macro == :belongs_to
|
7
|
-
|
8
|
-
association.name
|
9
|
-
end.compact
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
module IdsOfAllDirectDependencies
|
14
|
-
include SymbolsOfAllDirectDependencies
|
15
|
-
|
16
|
-
def ids_of_all_direct_dependencies
|
17
|
-
result = IdHash.new
|
18
|
-
|
19
|
-
self.class.reflect_on_all_associations.map do |association|
|
20
|
-
next if association.macro == :belongs_to
|
21
|
-
|
22
|
-
symbol = association.klass.name.underscore.to_sym
|
23
|
-
self.send(association.name).map do |associated_object|
|
24
|
-
result.add(symbol, associated_object.id)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
result
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
module IdsOfAllDependenciesNested
|
33
|
-
def ids_of_all_dependencies_nested(depth = Float::INFINITY)
|
34
|
-
result = depth > 0 ? get_associations(depth) : {}
|
35
|
-
result[:id] = id
|
36
|
-
result = result[:id] if result.size == 1
|
37
|
-
result
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def get_associations(depth)
|
43
|
-
result = {}
|
44
|
-
|
45
|
-
self.class.reflect_on_all_associations.map do |association|
|
46
|
-
next if association.macro == :belongs_to
|
47
|
-
|
48
|
-
symbol = association.klass.name.underscore.to_sym
|
49
|
-
self.send(association.name).sort_by(&:id).map do |associated_object|
|
50
|
-
result[symbol] = [] if result[symbol].nil?
|
51
|
-
result[symbol] << associated_object.ids_of_all_dependencies_nested(depth - 1)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
result
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
module DependencyTree
|
60
|
-
class Tree < Hash
|
61
|
-
def initialize(hash={})
|
62
|
-
hash.each do |key, value|
|
63
|
-
self[key] = value
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def ids_tree
|
68
|
-
self_cloned = self.deep_tree_clone
|
69
|
-
self_cloned.delete_key_recursive(:instance)
|
70
|
-
end
|
71
|
-
|
72
|
-
def status_tree
|
73
|
-
self_cloned = self.deep_tree_clone
|
74
|
-
|
75
|
-
self_cloned.do_recursive do |tree|
|
76
|
-
begin
|
77
|
-
tree[:instance].reload
|
78
|
-
tree[:status] = 'present'
|
79
|
-
rescue ActiveRecord::RecordNotFound => e
|
80
|
-
tree[:status] = 'removed'
|
81
|
-
end
|
82
|
-
|
83
|
-
tree.delete(:instance)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def status_tree_condensed
|
88
|
-
result = status_tree.do_recursive do |tree|
|
89
|
-
tree.each do |name, array|
|
90
|
-
next unless array.class == Array
|
91
|
-
|
92
|
-
new_array = array.map do |subtree|
|
93
|
-
next subtree.root_duplicate_summary if subtree[:duplicate]
|
94
|
-
next subtree if subtree.class != Tree || subtree.size > 2
|
95
|
-
|
96
|
-
subtree.root_summary
|
97
|
-
end
|
98
|
-
|
99
|
-
array.clear
|
100
|
-
array.concat(new_array)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
result.do_recursive do |tree|
|
105
|
-
tree[:_] = tree.root_summary
|
106
|
-
tree.delete(:id)
|
107
|
-
tree.delete(:status)
|
108
|
-
tree.last_to_beginning!
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def last_to_beginning!
|
113
|
-
arr = self.to_a
|
114
|
-
arr.unshift(arr.pop)
|
115
|
-
self.clear
|
116
|
-
self.merge!(arr.to_h)
|
117
|
-
end
|
118
|
-
|
119
|
-
def root_summary
|
120
|
-
"id #{self[:id]}, #{self[:status]}"
|
121
|
-
end
|
122
|
-
|
123
|
-
def root_duplicate_summary
|
124
|
-
root_summary + ", duplicate"
|
125
|
-
end
|
126
|
-
|
127
|
-
def deep_tree_clone
|
128
|
-
hash = self.clone.map do |key, array|
|
129
|
-
next [key, array] unless array.class == Array
|
130
|
-
|
131
|
-
new_array = array.map do |subtree|
|
132
|
-
if subtree.class == Tree
|
133
|
-
subtree.deep_tree_clone
|
134
|
-
else
|
135
|
-
subtree
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
[key, new_array]
|
140
|
-
end
|
141
|
-
|
142
|
-
Tree.new(hash)
|
143
|
-
end
|
144
|
-
|
145
|
-
def delete_key_recursive(key)
|
146
|
-
call_method_recursive(:delete, key)
|
147
|
-
end
|
148
|
-
|
149
|
-
def call_method_recursive(method, *args, &block)
|
150
|
-
do_recursive do |tree|
|
151
|
-
tree.send(method, *args, &block)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def do_recursive(&block)
|
156
|
-
block.call(self)
|
157
|
-
|
158
|
-
self.each do |key, array|
|
159
|
-
next unless array.is_a? Array
|
160
|
-
|
161
|
-
array.each do |subtree|
|
162
|
-
subtree.do_recursive(&block) if subtree.is_a? Tree
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
self
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def dependency_tree(depth = Float::INFINITY, hash_for_duplication_check = IdHash.new)
|
171
|
-
is_duplicate = hash_for_duplication_check[self.class]&.include?(id)
|
172
|
-
hash_for_duplication_check.add(self.class, id)
|
173
|
-
shoud_go_deeper = depth > 0 && !is_duplicate
|
174
|
-
result = shoud_go_deeper ? get_associations_for_tree(depth, hash_for_duplication_check) : Tree.new
|
175
|
-
result[:id] = id
|
176
|
-
result[:instance] = self
|
177
|
-
result[:duplicate] = true if is_duplicate
|
178
|
-
result
|
179
|
-
end
|
180
|
-
|
181
|
-
private
|
182
|
-
|
183
|
-
def get_associations_for_tree(depth, hash_for_duplication_check)
|
184
|
-
result = Tree.new
|
185
|
-
|
186
|
-
self.class.reflect_on_all_associations.map do |association|
|
187
|
-
next if association.macro == :belongs_to
|
188
|
-
|
189
|
-
symbol = association.klass.name.underscore.to_sym
|
190
|
-
self.send(association.name).sort_by(&:id).map do |associated_object|
|
191
|
-
result[symbol] = [] if result[symbol].nil?
|
192
|
-
result[symbol] << associated_object.dependency_tree(depth - 1, hash_for_duplication_check)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
result
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
3
|
module IdsOfAllDependencies
|
201
|
-
|
202
|
-
|
203
|
-
|
4
|
+
def self.get_model(name)
|
5
|
+
self.subclasses.find{ |m| m.name == name.to_s.camelcase }
|
6
|
+
end
|
204
7
|
|
205
8
|
def ids_of_all_dependencies(to_filter=nil, filtering_strategy=:with_parents)
|
206
9
|
ids_of_all_dependencies_with_filtered(to_filter, filtering_strategy)[:main]
|
@@ -302,7 +105,7 @@ module IdsOfAllDependencies
|
|
302
105
|
def move_wrongly_assigned_to_main(to_filter, id_hash)
|
303
106
|
id_hash[:filtered_out].each do |model_symbol, array|
|
304
107
|
array.clone.each do |id|
|
305
|
-
object =
|
108
|
+
object = self.class.get_model(model_symbol).find(id)
|
306
109
|
move_object_to_main_if_necessary(to_filter[model_symbol], id_hash, object)
|
307
110
|
end
|
308
111
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module IdsOfAllDependenciesNested
|
2
|
+
def ids_of_all_dependencies_nested(depth = Float::INFINITY)
|
3
|
+
result = depth > 0 ? get_associations(depth) : {}
|
4
|
+
result[:id] = id
|
5
|
+
result = result[:id] if result.size == 1
|
6
|
+
result
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def get_associations(depth)
|
12
|
+
result = {}
|
13
|
+
|
14
|
+
self.class.reflect_on_all_associations.map do |association|
|
15
|
+
next if association.macro == :belongs_to
|
16
|
+
|
17
|
+
symbol = association.klass.name.underscore.to_sym
|
18
|
+
self.send(association.name).sort_by(&:id).map do |associated_object|
|
19
|
+
result[symbol] = [] if result[symbol].nil?
|
20
|
+
result[symbol] << associated_object.ids_of_all_dependencies_nested(depth - 1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'id_hash'
|
2
|
+
|
3
|
+
module IdsOfAllDirectDependencies
|
4
|
+
def ids_of_all_direct_dependencies
|
5
|
+
result = IdHash.new
|
6
|
+
|
7
|
+
self.class.reflect_on_all_associations.map do |association|
|
8
|
+
next if association.macro == :belongs_to
|
9
|
+
|
10
|
+
symbol = association.klass.name.underscore.to_sym
|
11
|
+
self.send(association.name).map do |associated_object|
|
12
|
+
result.add(symbol, associated_object.id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NullifyDependencies
|
4
|
+
def nullify_dependencies(dependencies_symbols_to_nullify)
|
5
|
+
dependencies_symbols_to_nullify.map do |symbol|
|
6
|
+
dependencies = self.send(symbol) # e.g. build.tags_for_that_this_build_is_last
|
7
|
+
|
8
|
+
dependencies.map do |entry|
|
9
|
+
foreign_key = self.class.reflect_on_association(symbol).foreign_key.to_sym
|
10
|
+
entry.update(foreign_key => nil) # e.g. tag.update(last_build_id: nil)
|
11
|
+
{
|
12
|
+
related_table: entry.class.table_name,
|
13
|
+
foreign_key: foreign_key,
|
14
|
+
parent_id: self.id,
|
15
|
+
related_id: entry.id
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def nullify_all_dependencies
|
22
|
+
nullify_dependencies(symbols_of_all_direct_dependencies)
|
23
|
+
end
|
24
|
+
|
25
|
+
def nullify_default_dependencies
|
26
|
+
nullify_dependencies(default_dependencies_symbols_to_nullify)
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_dependencies_symbols_to_nullify
|
30
|
+
self.class.default_dependencies_symbols_to_nullify
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.default_dependencies_symbols_to_nullify
|
34
|
+
raise "self.default_dependencies_symbols_to_nullify not implemented in the #{self.class} class"
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_dependencies_to_nullify
|
38
|
+
default_dependencies_symbols_to_nullify.map do |symbol|
|
39
|
+
self.send(symbol).to_a
|
40
|
+
end.flatten(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
def symbols_of_all_direct_dependencies
|
44
|
+
self.class.reflect_on_all_associations.map do |association|
|
45
|
+
next if association.macro == :belongs_to
|
46
|
+
|
47
|
+
association.name
|
48
|
+
end.compact
|
49
|
+
end
|
50
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependency-trees
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karol Selak
|
@@ -215,10 +215,16 @@ files:
|
|
215
215
|
- Gemfile
|
216
216
|
- dependency-trees-0.0.1.gem
|
217
217
|
- dependency-trees-0.0.2.gem
|
218
|
+
- dependency-trees-0.0.3.gem
|
219
|
+
- dependency-trees-0.0.4.gem
|
218
220
|
- dependency-trees.gemspec
|
219
221
|
- lib/dependency-trees.rb
|
222
|
+
- lib/dependency_tree.rb
|
220
223
|
- lib/id_hash.rb
|
221
224
|
- lib/ids_of_all_dependencies.rb
|
225
|
+
- lib/ids_of_all_dependencies_nested.rb
|
226
|
+
- lib/ids_of_all_direct_dependencies.rb
|
227
|
+
- lib/nullify_dependencies.rb
|
222
228
|
homepage:
|
223
229
|
licenses:
|
224
230
|
- MIT
|