module ActiveRecord::Acts::TreeWithDottedIds::InstanceMethods

Public Instance Methods

all_children() click to toggle source

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
ancestor_of?(node) click to toggle source

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
ancestors() click to toggle source

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
depth() click to toggle source

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
descendant_of?(node) click to toggle source

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
root() click to toggle source

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
self_and_all_children() click to toggle source

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
self_and_ancestors() click to toggle source
# File lib/active_record/acts/tree_with_dotted_ids.rb, line 117
def self_and_ancestors
  [self] + ancestors
end
self_and_siblings() click to toggle source

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
siblings() click to toggle source

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

assign_dotted_ids() click to toggle source

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
build_dotted_ids() click to toggle source

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
dotted_id_like_pattern(prefix = nil) click to toggle source

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_dotted_ids(prefix = nil, extra_scope = self.class.where('1=1')) click to toggle source

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
update_dotted_ids() click to toggle source

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