hierarchy-tree 0.1.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 +7 -0
  2. data/lib/hierarchy_tree.rb +97 -0
  3. metadata +90 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c69d1d28db8ef461d3a9dbdc093cee55aeb3899d0127965f5f282402e3a92d20
4
+ data.tar.gz: 66637e5ac94c03c4add0fe2373141761ce89cb96aeff0b0bf7eda20cdda1a50c
5
+ SHA512:
6
+ metadata.gz: 4d24c501e41cf7594dd4ade171659fda73b0fde49dd812bd4ac05af3e1fc77b77e9845b101972e067db10cb54af3890d19ed84f1bbddd8b20d1fcac7d1e227dd
7
+ data.tar.gz: 006ad25440512ff39490a5b7ed8988c7b34c0ce2f73d4085a6947c9cd4e00e2e70f653560c386ff02d8a6e3e3e0ab8ef5bf14ccc09db9f01d641e1fe493b0b72
@@ -0,0 +1,97 @@
1
+ require 'active_record'
2
+ require 'active_support/core_ext/object/inclusion.rb'
3
+
4
+ class Hierarchy
5
+ # Return the full hierarchy starting from the provided class
6
+ def self.associations(klass)
7
+ build_hierarchy(klass)
8
+ end
9
+
10
+ # Return just the descendant classes of a provided class
11
+ def self.descendants(klass)
12
+ @descendants = []
13
+ build_descendants(klass)
14
+ @descendants
15
+ end
16
+
17
+ def self.loop?(klass)
18
+ @cache = {}
19
+ false if dfs_hierarchy(class: klass, classes?: false)
20
+ rescue SystemStackError
21
+ true
22
+ end
23
+
24
+ private_class_method
25
+
26
+ def self.build_hierarchy(klass)
27
+ @cache = {}
28
+ dfs_hierarchy(class: klass)
29
+ rescue SystemStackError
30
+ Rails.logger.ap "Infinite loop detected and handled for #{opts[:class]} hierarchy", :warn
31
+ []
32
+ end
33
+
34
+ def self.dfs_hierarchy(opts, klass_name = nil, ancestral_nodes = [])
35
+ return @cache[klass_name] if klass_name.in? @cache.keys
36
+ return klass_name if opts[:class].in? ancestral_nodes # Early abort to not enter in a cycle
37
+ if leaf?(opts[:class])
38
+ @cache[klass_name] = klass_name
39
+ return klass_name if klass_name.present? # Leaf
40
+ [] # Leaf and Root
41
+ else
42
+ ancestral_nodes.push(opts[:class])
43
+ children_hierarchies = children_classes(opts).map do |c_class, c_name|
44
+ dfs_hierarchy({ class: c_class, classes?: opts[:classes?] }, c_name, ancestral_nodes.dup)
45
+ end
46
+ @cache[klass_name] = { klass_name => children_hierarchies }
47
+ return @cache[klass_name] if klass_name.present? # Middle
48
+ children_hierarchies # Root
49
+ end
50
+ end
51
+
52
+ def self.leaf?(klass)
53
+ return true if walkables(klass).empty?
54
+ false
55
+ end
56
+
57
+ def self.children_classes(opts)
58
+ walkables(opts[:class]).map do |reflection|
59
+ child_class = get_class(reflection)
60
+ if opts[:classes?]
61
+ [child_class, child_class.to_s]
62
+ else
63
+ [child_class, reflection.name]
64
+ end
65
+ end.uniq
66
+ end
67
+
68
+ def self.walkables(klass)
69
+ # get all models associated with :has_many or :has_one that are walkable.
70
+ klass.reflections.values.select do |r|
71
+ r.macro.in? %i[has_one has_many] and not r.options.key?(:through)
72
+ end
73
+ end
74
+
75
+ def self.get_class(reflection)
76
+ child = reflection.name.to_s.singularize.classify
77
+ child = reflection.options[:class_name].to_s if reflection.options.key?(:class_name)
78
+ child.constantize
79
+ end
80
+
81
+ def self.build_descendants(klass)
82
+ dfs_descendants(class: klass, classes?: true)
83
+ rescue SystemStackError
84
+ Rails.logger.ap "Infinite loop detected and handled for #{opts[:class]} descendants", :warn
85
+ []
86
+ end
87
+
88
+ def self.dfs_descendants(opts, klass_name = nil)
89
+ return if klass_name.in? @descendants
90
+ @descendants.push(klass_name) if klass_name.present?
91
+ children_classes(opts).each do |child_klass, child_name|
92
+ child_opts = { class: child_klass, classes?: opts[:classes?] }
93
+ dfs_descendants(child_opts, child_name)
94
+ end
95
+ true
96
+ end
97
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hierarchy-tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Victor Cordeiro Costa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.2'
55
+ description: |-
56
+ hierarchy-tree is a gem that shows the whole hierarchy
57
+ and the associations related to a desired class.
58
+ email:
59
+ - victorcorcos@gmail.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - lib/hierarchy_tree.rb
65
+ homepage: https://github.com/Victorcorcos/hierarchy-tree
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '2.0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.7.9
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: hierarchy-tree is a gem that shows the whole hierarchy and the associations
89
+ related to a desired class.
90
+ test_files: []