hierarchy-tree 0.2.0 → 0.3.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/hierarchy_tree.rb +71 -5
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c2620a107d595da64c5854efec9c90f4ebada54e79ea851e35cd698dd31cb7e
4
- data.tar.gz: 3957eb61b1debe9dcff8049d89947a60b594b348f3e65b31f25615d4bb56a8de
3
+ metadata.gz: cab69803c942b2cda581356ae1c3701febf660db154041a799d0c2dd22eefbfa
4
+ data.tar.gz: de33c12ba0a884a268d0730a3fce604591b9d62ff5b07e994e583b9e8524316a
5
5
  SHA512:
6
- metadata.gz: cfe0cdf719a378c501ac89db2df73349f9af3b131c39947e0ad3b9126032ca2898997fad85f4ae532b30fa11062e84fbc339c5a7d6e2cd7f092d486426a84040
7
- data.tar.gz: 0b3677fe95dd795eb1ba93671e9878df59e712d4378c0a638cb62765f7bc49fef2e8ab8e91133934723afb2b91149a6984b25353d383911d7d516bd6539dd9bf
6
+ metadata.gz: eecf514e48906d8fcc98e5c80896e56b0d2cf1d2f60d207ce644dc72b131c35fe0d6329d3f786cb2ed35df8f113bf9c11d6b3083835a39e7600c22adc7d3c631
7
+ data.tar.gz: 9dacd1c66e4bb7355eeee8bf51341bcfa3d3a6cea7d76b6bce0a6057614e48a6bf8751ba064da6ec54b5f84cb1a41063e3c7904c4f8fbf12cec4db86905e98cf
@@ -2,29 +2,74 @@ require 'active_record'
2
2
  require 'active_support/core_ext/object/inclusion.rb'
3
3
 
4
4
  ################ Debug ################
5
- # rm hierarchy-tree-X.Y.Z.gem
5
+ # gem uninstall hierarchy-tree -v 0.3.0
6
+ # rm hierarchy-tree-0.3.0.gem
6
7
  # gem build hierarchy_tree
7
- # gem install hierarchy-tree-X.Y.Z.gem
8
+ # gem install hierarchy-tree-0.3.0.gem
8
9
  # ruby -Itest test/test_hierarchy_tree.rb
9
10
 
10
11
  class Hierarchy
11
- # Return the full hierarchy starting from the provided class
12
+ # Return the full hierarchy as associations starting from the provided class
12
13
  def self.associations(klass)
13
14
  build_hierarchy(class: klass)
14
15
  end
15
16
 
16
- # Return the full hierarchy starting from the provided class
17
+ # Return the full hierarchy as classes starting from the provided class
17
18
  def self.classes(klass)
18
19
  build_hierarchy(class: klass, classes?: true)
19
20
  end
20
21
 
21
- # Return an array o
22
+ # Return the array of children classes
22
23
  def self.classes_list(klass)
23
24
  @classes_list = []
24
25
  build_descendants(klass)
25
26
  @classes_list
26
27
  end
27
28
 
29
+ # Return the ancestors associations by navigating through :belongs_to
30
+ # Starting from the "from" class towards the "to" class
31
+ # Using DFS - Depth First Search, thus finding the Deepest Path (more likely)
32
+ def self.ancestors_dfs(from:, to:, descendants: [])
33
+ return if from.to_s == to.to_s and descendants == [] # Base case
34
+ return 'loop' if from.in? descendants # Avoids cycle
35
+
36
+ descendants.push(from)
37
+
38
+ from.reflect_on_all_associations(:belongs_to).map do |relation|
39
+ return relation.name if relation.klass.to_s == to.to_s # Path is found
40
+ path = ancestors_dfs(from: relation.klass, to: to, descendants: descendants)
41
+ return { relation.name => path } if valid_path?(path, to.model_name.param_key.to_sym)
42
+ end.compact.first
43
+ end
44
+
45
+ # Return the ancestors associations by navigating through :belongs_to
46
+ # Starting from the "from" class towards the "to" class
47
+ # Using BFS - Breadth First Search, thus finding the Shortest Path
48
+ def self.ancestors_bfs(from:, to:)
49
+ return if from == to
50
+
51
+ queue = [{ class: from, path: [] }]
52
+ visited = [from]
53
+
54
+ while queue.any?
55
+ current = queue.shift
56
+ current_class = current[:class]
57
+ current_path = current[:path]
58
+
59
+ current_class.reflect_on_all_associations(:belongs_to).each do |relation|
60
+ next_class = relation.klass
61
+ next_path = current_path + [relation.name]
62
+
63
+ return hashify(next_path) if next_class.to_s == to.to_s
64
+
65
+ if visited.exclude?(next_class)
66
+ visited << next_class
67
+ queue.push({ class: next_class, path: next_path })
68
+ end
69
+ end
70
+ end
71
+ end
72
+
28
73
  def self.loop?(klass)
29
74
  @cache = {}
30
75
  false if dfs_hierarchy(class: klass, classes?: false)
@@ -105,4 +150,25 @@ class Hierarchy
105
150
  end
106
151
  true
107
152
  end
153
+
154
+ def self.valid_path?(path, target)
155
+ return true if path == target
156
+
157
+ case path
158
+ when Array
159
+ path.any? { |sub_path| valid_path?(sub_path, target) }
160
+ when Hash
161
+ path.values.any? { |value| valid_path?(value, target) }
162
+ else
163
+ false
164
+ end
165
+ 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
108
174
  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.2.0
4
+ version: 0.3.0
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-13 00:00:00.000000000 Z
11
+ date: 2023-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest