module ActiveRecord::Acts::TreeWithDottedIds::InstanceMethods
Public Instance Methods
Returns all children of the current node root.all_children # => [child1, subchild1, subchild2]
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 163 def all_children find_all_children_with_dotted_ids end
root.ancestor_of?(subchild1) # => true subchild1.ancestor_of?(child1) # => false
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 150 def ancestor_of?(node) node.dotted_ids.length > self.dotted_ids.length && node.dotted_ids.starts_with?(self.dotted_ids) end
Returns list of ancestors, starting from parent until root.
subchild1.ancestors # => [child1, root]
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 105 def ancestors if self.dotted_ids ids = self.dotted_ids.split('.')[0...-1] self.class.where(:id => ids).order('dotted_ids DESC') else node, nodes = self, [] nodes << node = node.parent while node.parent nodes end end
Returns the depth of the node, root nodes have a depth of 0
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 174 def depth if self.dotted_ids.present? self.dotted_ids.scan(/\./).size else (self.parent.try(:depth) || -1) + 1 end end
subchild1.descendant_of?(child1) # => true root.descendant_of?(subchild1) # => false
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 157 def descendant_of?(node) self.dotted_ids.length > node.dotted_ids.length && self.dotted_ids.starts_with?(node.dotted_ids) end
Returns the root node of the tree.
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 122 def root if self.dotted_ids self.class.find(self.dotted_ids.split('.').first) else node = self node = node.parent while node.parent node end end
Returns all children of the current node root.self_and_all_children # => [root, child1, subchild1, subchild2]
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 169 def self_and_all_children [self] + all_children end
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 117 def self_and_ancestors [self] + ancestors end
Returns all siblings and a reference to the current node.
subchild1.self_and_siblings # => [subchild1, subchild2]
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 142 def self_and_siblings #parent ? parent.children : self.class.roots self.class.where(:parent_id => self.parent_id) end
Returns all siblings of the current node.
subchild1.siblings # => [subchild2]
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 135 def siblings self_and_siblings - [self] end
Protected Instance Methods
After create, adds the dotted id’s
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 202 def assign_dotted_ids self.update_attribute(:dotted_ids, build_dotted_ids) if self.dotted_ids.blank? end
Generates the dotted_ids for this node
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 197 def build_dotted_ids self.parent ? "#{self.parent.dotted_ids}.#{self.id}" : self.id.to_s end
Tranforms a dotted_id string into a pattern usable with a SQL LIKE statement
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 185 def dotted_id_like_pattern(prefix = nil) (prefix || self.dotted_ids) + '.%' end
Find all children with the given dotted_id prefix extra_scope will be combine with dotted_ids LIKE FIXME: use extra_scope when it will be part of the public API
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 192 def find_all_children_with_dotted_ids(prefix = nil, extra_scope = self.class.where('1=1')) extra_scope.where('dotted_ids LIKE ?', dotted_id_like_pattern(prefix)) end
After validation on update, rebuild dotted ids if necessary
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 207 def update_dotted_ids return unless parent_foreign_key_changed? old_dotted_ids = self.dotted_ids old_dotted_ids_regex = Regexp.new("^#{Regexp.escape(old_dotted_ids)}(.*)") self.dotted_ids = build_dotted_ids replace_pattern = "#{self.dotted_ids}\\1" find_all_children_with_dotted_ids(old_dotted_ids).each do |node| new_dotted_ids = node.dotted_ids.gsub(old_dotted_ids_regex, replace_pattern) node.update_attribute(:dotted_ids, new_dotted_ids) end end