Created
March 7, 2019 17:57
-
-
Save madwork/0aa28576a7e712efddc88d9bc28f554e to your computer and use it in GitHub Desktop.
Tree with apples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Tree | |
# Returns list of ancestors, starting from parent until root. | |
# | |
# subchild1.ancestors # => [child1, root] | |
def ancestors | |
node, nodes = self, [] | |
nodes << node = node.parent while node.parent | |
nodes | |
end | |
# Returns list of descendants, starting from current node, not including current node. | |
# | |
# root.descendants # => [child1, child2, subchild1, subchild2, subchild3, subchild4] | |
def descendants | |
children.each_with_object(children.to_a) {|child, arr| | |
arr.concat child.descendants | |
}.uniq | |
end | |
# Returns list of descendants, starting from current node, including current node. | |
# | |
# root.self_and_descendants # => [root, child1, child2, subchild1, subchild2, subchild3, subchild4] | |
def self_and_descendants | |
[self] + descendants | |
end | |
# Returns the root node of the tree. | |
def root | |
node = self | |
node = node.parent while node.parent | |
node | |
end | |
# Returns all siblings of the current node. | |
# | |
# subchild1.siblings # => [subchild2] | |
def siblings | |
self_and_siblings - [self] | |
end | |
# Returns all siblings and a reference to the current node. | |
# | |
# subchild1.self_and_siblings # => [subchild1, subchild2] | |
def self_and_siblings | |
parent ? parent.children : self.class.roots | |
end | |
# Returns all the nodes at the same level in the tree as the current node. | |
# | |
# root1child1.generation # => [root1child2, root2child1, root2child2] | |
def generation | |
self_and_generation - [self] | |
end | |
# Returns a reference to the current node and all the nodes at the same level as it in the tree. | |
# | |
# root1child1.self_and_generation # => [root1child1, root1child2, root2child1, root2child2] | |
def self_and_generation | |
self.class.select {|node| node.tree_level == self.tree_level } | |
end | |
# Returns the level (depth) of the current node | |
# | |
# root1child1.tree_level # => 1 | |
def tree_level | |
self.ancestors.size | |
end | |
# Returns the level (depth) of the current node unless level is a column on the node. | |
# Allows backwards compatibility with older versions of the gem. | |
# Allows integration with apps using level as a column name. | |
# | |
# root1child1.level # => 1 | |
def level | |
if self.class.column_names.include?('level') | |
super | |
else | |
tree_level | |
end | |
end | |
# Returns children (without subchildren) and current node itself. | |
# | |
# root.self_and_children # => [root, child1] | |
def self_and_children | |
[self] + self.children | |
end | |
# Returns ancestors and current node itself. | |
# | |
# subchild1.self_and_ancestors # => [subchild1, child1, root] | |
def self_and_ancestors | |
[self] + self.ancestors | |
end | |
# Returns true if node has no parent, false otherwise | |
# | |
# subchild1.root? # => false | |
# root.root? # => true | |
def root? | |
parent.nil? | |
end | |
# Returns true if node has no children, false otherwise | |
# | |
# subchild1.leaf? # => true | |
# child1.leaf? # => false | |
def leaf? | |
children.size.zero? | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment