Module: PathTree
- Includes:
- Patterns
- Defined in:
- lib/path_tree.rb,
lib/path_tree/version.rb,
lib/path_tree/patterns.rb
Overview
This module implements a tree structure by using a convention of converting a name into a path. Paths created by normalizing a name attribute and then separating levels with periods with the lowest level coming last.
In order to use this module, the model must respond to the first and all methods like ActiveRecord, have support for after_destroy and after_save callbacks, validates_* macros and include attributes for name, node_path, path, and parent_path.
Defined Under Namespace
Modules: ClassMethods, Patterns
Constant Summary collapse
- VERSION =
'1.1.0'.freeze
Constants included from Patterns
Patterns::LOWER_AE_PATTERN, Patterns::LOWER_A_PATTERN, Patterns::LOWER_C_PATTERN, Patterns::LOWER_E_PATTERN, Patterns::LOWER_I_PATTERN, Patterns::LOWER_N_PATTERN, Patterns::LOWER_O_PATTERN, Patterns::LOWER_U_PATTERN, Patterns::LOWER_Y_PATTERN, Patterns::SS_PATTERN, Patterns::UPPER_AE_PATTERN, Patterns::UPPER_A_PATTERN, Patterns::UPPER_C_PATTERN, Patterns::UPPER_D_PATTERN, Patterns::UPPER_E_PATTERN, Patterns::UPPER_I_PATTERN, Patterns::UPPER_N_PATTERN, Patterns::UPPER_O_PATTERN, Patterns::UPPER_U_PATTERN, Patterns::UPPER_Y_PATTERN
Class Method Summary collapse
Instance Method Summary collapse
-
#ancestors ⇒ Object
Get all ancestors of this node with the root node first.
-
#children ⇒ Object
Get all nodes that are direct children of this node.
-
#descendants ⇒ Object
Get all descendant of this node.
-
#expanded_paths ⇒ Object
Returns an array containing the paths of this node and those of all its ancestors.
-
#full_name(options = {}) ⇒ Object
Get the full name of a node including the names of all it’s parent nodes.
- #name=(value) ⇒ Object
- #node_path=(value) ⇒ Object
-
#parent ⇒ Object
Get the parent node.
-
#parent=(node) ⇒ Object
Set the parent node.
-
#parent_path=(value) ⇒ Object
Set the parent path.
- #path_delimiter ⇒ Object
-
#siblings ⇒ Object
Get all nodes that share the same parent as this node.
Class Method Details
.included(base) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/path_tree.rb', line 13 def self.included (base) base.extend(ClassMethods) base.validates_uniqueness_of :path base.validates_uniqueness_of :node_path, :scope => :parent_path base.validates_presence_of :name, :node_path, :path base.after_save do |record| if record.path_changed? and !record.path_was.nil? record.children.each do |child| child.update_attributes(:parent_path => record.path) end end record.instance_variable_set(:@children, nil) end base.after_destroy do |record| record.children.each do |child| child.update_attributes(:parent_path => record.parent_path) end end end |
Instance Method Details
#ancestors ⇒ Object
Get all ancestors of this node with the root node first.
218 219 220 221 222 223 224 225 226 |
# File 'lib/path_tree.rb', line 218 def ancestors ancestor_paths = ancestor_paths.pop if ancestor_paths.empty? [] else self.class.base_class.where(path: ancestor_paths).to_a.sort{|a,b| a.path.length <=> b.path.length} end end |
#children ⇒ Object
Get all nodes that are direct children of this node.
197 198 199 200 201 202 203 204 |
# File 'lib/path_tree.rb', line 197 def children unless @children childrens_path = new_record? ? path : path_was @children = self.class.base_class.where(parent_path: childrens_path).to_a @children.each{|c| c.parent = self} end @children end |
#descendants ⇒ Object
Get all descendant of this node.
213 214 215 |
# File 'lib/path_tree.rb', line 213 def descendants self.class.base_class.path_like(path) end |
#expanded_paths ⇒ Object
Returns an array containing the paths of this node and those of all its ancestors.
229 230 231 |
# File 'lib/path_tree.rb', line 229 def self.class.(path) end |
#full_name(options = {}) ⇒ Object
Get the full name of a node including the names of all it’s parent nodes. Specify the separator string to use between values with :separator (defaults to “ > ”). You can also specify the context for the full name by specifying a path in :context. This will only render the names up to and not including that part of the tree.
141 142 143 144 145 146 147 |
# File 'lib/path_tree.rb', line 141 def full_name ( = {}) separator = [:separator] || " > " n = "" n << parent.full_name() if parent_path and parent_path != [:context] n << separator unless n.blank? n << name end |
#name=(value) ⇒ Object
182 183 184 185 186 187 188 |
# File 'lib/path_tree.rb', line 182 def name= (value) unless value == name self[:name] = value self.node_path = value if node_path.blank? end value end |
#node_path=(value) ⇒ Object
190 191 192 193 194 |
# File 'lib/path_tree.rb', line 190 def node_path= (value) pathified = self.class.pathify(value) self[:node_path] = pathified recalculate_path end |
#parent ⇒ Object
Get the parent node.
154 155 156 157 158 159 160 161 162 163 |
# File 'lib/path_tree.rb', line 154 def parent unless instance_variable_defined?(:@parent) if path.index(path_delimiter) @parent = self.class.base_class.where(path: parent_path).first else @parent = nil end end @parent end |
#parent=(node) ⇒ Object
Set the parent node.
166 167 168 169 170 |
# File 'lib/path_tree.rb', line 166 def parent= (node) node_path = node.path if node self.parent_path = node_path unless parent_path == node_path @parent = node end |
#parent_path=(value) ⇒ Object
Set the parent path
173 174 175 176 177 178 179 180 |
# File 'lib/path_tree.rb', line 173 def parent_path= (value) unless value == parent_path self[:parent_path] = value recalculate_path remove_instance_variable(:@parent) if instance_variable_defined?(:@parent) end value end |
#path_delimiter ⇒ Object
149 150 151 |
# File 'lib/path_tree.rb', line 149 def path_delimiter self.class.path_delimiter end |
#siblings ⇒ Object
Get all nodes that share the same parent as this node.
207 208 209 210 |
# File 'lib/path_tree.rb', line 207 def siblings # OPTIMIZE if this record has an ID, it may be more efficient to exclude it via query rather than using reject self.class.base_class.where(parent_path: parent_path).to_a.reject{|node| node == self } end |