hierarchy-tree 0.3.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hierarchy_tree.rb +52 -22
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d4301de42dc78d8664798e551f846073a2bd7a79a2f5d5245d5c9e9339145c4
|
4
|
+
data.tar.gz: 73f7863eb9059605923a62c27dcc4baa3193509d5c0240f178e33f185e10df2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1567fd7d03e5e87ba9b8efe378a9ec15361352e9631229fa75b547905c762999d7315f4749841594aa2e1bd306a81f133d742f581fb76aa7dbe8523cf23754da
|
7
|
+
data.tar.gz: e371543dcc4e11f0946595218da4beaf1bb792b596988d16b417c5441d00f5d4e0492f2f740acaae869e83bd336c8a27de57161c86e7e448a56c28461b3f6070
|
data/lib/hierarchy_tree.rb
CHANGED
@@ -2,10 +2,10 @@ require 'active_record'
|
|
2
2
|
require 'active_support/core_ext/object/inclusion.rb'
|
3
3
|
|
4
4
|
################ Debug ################
|
5
|
-
# gem
|
6
|
-
# rm hierarchy-tree-
|
5
|
+
# gem cleanup hierarchy-tree
|
6
|
+
# rm hierarchy-tree-X.Y.Z.gem
|
7
7
|
# gem build hierarchy_tree
|
8
|
-
# gem install hierarchy-tree-
|
8
|
+
# gem install hierarchy-tree-X.Y.Z.gem
|
9
9
|
# ruby -Itest test/test_hierarchy_tree.rb
|
10
10
|
|
11
11
|
class Hierarchy
|
@@ -26,20 +26,34 @@ class Hierarchy
|
|
26
26
|
@classes_list
|
27
27
|
end
|
28
28
|
|
29
|
-
# Return the ancestors associations by navigating through :belongs_to
|
29
|
+
# Return all the possible ancestors associations by navigating through :belongs_to
|
30
30
|
# Starting from the "from" class towards the "to" class
|
31
|
-
|
32
|
-
|
33
|
-
return if from.to_s == to.to_s and descendants == [] # Base case
|
34
|
-
return 'loop' if from.in? descendants # Avoids cycle
|
31
|
+
def self.ancestors(from:, to:)
|
32
|
+
return [] if from.to_s == to.to_s
|
35
33
|
|
36
|
-
|
34
|
+
queue = [{ class: from.to_s, path: [] }]
|
35
|
+
visited = { from.to_s => [] }
|
36
|
+
paths = []
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
while queue.any?
|
39
|
+
current = queue.shift
|
40
|
+
current_class = current[:class]
|
41
|
+
current_path = current[:path]
|
42
|
+
|
43
|
+
current_class.constantize.reflect_on_all_associations(:belongs_to).each do |relation|
|
44
|
+
next_class = relation.klass.to_s
|
45
|
+
next_path = current_path + [relation.name]
|
46
|
+
|
47
|
+
paths << hashify(next_path) if next_class == to.to_s
|
48
|
+
|
49
|
+
if relation.class_name != from.name and next_path == next_path.uniq # Non-looped path
|
50
|
+
visited[next_class] = next_path
|
51
|
+
queue.push({ class: next_class, path: next_path })
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
paths
|
43
57
|
end
|
44
58
|
|
45
59
|
# Return the ancestors associations by navigating through :belongs_to
|
@@ -70,6 +84,22 @@ class Hierarchy
|
|
70
84
|
end
|
71
85
|
end
|
72
86
|
|
87
|
+
# Return the ancestors associations by navigating through :belongs_to
|
88
|
+
# Starting from the "from" class towards the "to" class
|
89
|
+
# Using DFS - Depth First Search, thus finding the Deepest Path (more likely)
|
90
|
+
def self.ancestors_dfs(from:, to:, descendants: [])
|
91
|
+
return if from.to_s == to.to_s and descendants == [] # Base case
|
92
|
+
return 'loop' if from.in? descendants # Avoids cycle
|
93
|
+
|
94
|
+
descendants.push(from)
|
95
|
+
|
96
|
+
from.reflect_on_all_associations(:belongs_to).map do |relation|
|
97
|
+
return relation.name if relation.klass.to_s == to.to_s # Path is found
|
98
|
+
path = ancestors_dfs(from: relation.klass, to: to, descendants: descendants)
|
99
|
+
return { relation.name => path } if valid_path?(path, to.model_name.param_key.to_sym)
|
100
|
+
end.compact.first
|
101
|
+
end
|
102
|
+
|
73
103
|
def self.loop?(klass)
|
74
104
|
@cache = {}
|
75
105
|
false if dfs_hierarchy(class: klass, classes?: false)
|
@@ -151,6 +181,14 @@ class Hierarchy
|
|
151
181
|
true
|
152
182
|
end
|
153
183
|
|
184
|
+
def self.hashify(array)
|
185
|
+
if array.length == 1
|
186
|
+
array.first
|
187
|
+
else
|
188
|
+
{ array.first => hashify(array.drop(1)) }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
154
192
|
def self.valid_path?(path, target)
|
155
193
|
return true if path == target
|
156
194
|
|
@@ -163,12 +201,4 @@ class Hierarchy
|
|
163
201
|
false
|
164
202
|
end
|
165
203
|
end
|
166
|
-
|
167
|
-
def self.hashify(array)
|
168
|
-
if array.length == 1
|
169
|
-
array.first
|
170
|
-
else
|
171
|
-
{ array.first => hashify(array.drop(1)) }
|
172
|
-
end
|
173
|
-
end
|
174
204
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hierarchy-tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Cordeiro Costa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|