# Fetch tree node if necessary
def to_node object
# Scope on relative depth options
def scope_depth depth_options, depth
# Orphan strategy writer
def orphan_strategy= orphan_strategy
# Arrangement
def arrange options = {}
# Arrange array of nodes into a nested hash of the form
# {node => children}, where children = {} if the node has no children
def arrange_nodes(nodes)
# Pseudo-preordered array of nodes. Children will always follow parents,
# but the ordering of nodes within a rank depends on their order in the
# array that gets passed in
def sort_by_ancestry(nodes)
# Integrity checking
def check_ancestry_integrity! options = {}
# Integrity restoration
def restore_ancestry_integrity!
# Build ancestry from parent id's for migration purposes
def build_ancestry_from_parent_ids! parent_id = nil, ancestry = nil
# Rebuild depth cache if it got corrupted or if depth caching was just turned on
def rebuild_depth_cache!
class << ActiveRecord::Base
def has_ancestry options = {}
some codes ~~~~
end
# Alias has_ancestry with acts_as_tree, if it's available.
if !defined?(ActsAsTree)
alias_method :acts_as_tree, :has_ancestry
end
end
(除开头 4 个外,共细分为 八 个方面。)
module Ancestry
module InstanceMethods
``` ruby
# Validate that the ancestors don't include itself
def ancestry_exclude_self
# Update descendants with new ancestry
def update_descendants_with_new_ancestry
# Apply orphan strategy
def apply_orphan_strategy
# The ancestry value for this record's children
def child_ancestry
# Ancestors
def ancestor_ids
read_attribute(self.base_class.ancestry_column).to_s.split('/').map { |id| cast_primary_key(id) }
end
def ancestor_conditions
{self.base_class.primary_key => ancestor_ids}
end
def ancestors depth_options = {}
self.base_class.scope_depth(depth_options, depth).ordered_by_ancestry.scoped :conditions => ancestor_conditions
end
def path_ids
ancestor_ids + [id]
end
def path_conditions
{self.base_class.primary_key => path_ids}
end
def path depth_options = {}
self.base_class.scope_depth(depth_options, depth).ordered_by_ancestry.scoped :conditions => path_conditions
end
def depth
ancestor_ids.size
end
def cache_depth
write_attribute self.base_class.depth_cache_column, depth
end
# Parent
def parent= parent
write_attribute(self.base_class.ancestry_column, if parent.blank? then nil else parent.child_ancestry end)
end
def parent_id= parent_id
self.parent = if parent_id.blank? then nil else self.base_class.find(parent_id) end
end
def parent_id
if ancestor_ids.empty? then nil else ancestor_ids.last end
end
def parent
if parent_id.blank? then nil else self.base_class.find(parent_id) end
end
# Root
def root_id
if ancestor_ids.empty? then id else ancestor_ids.first end
end
def root
if root_id == id then self else self.base_class.find(root_id) end
end
def is_root?
read_attribute(self.base_class.ancestry_column).blank?
end
# Children
def child_conditions
{self.base_class.ancestry_column => child_ancestry}
end
def children
self.base_class.scoped :conditions => child_conditions
end
def child_ids
children.all(:select => self.base_class.primary_key).map(&self.base_class.primary_key.to_sym)
end
def has_children?
self.children.exists?({})
end
def is_childless?
!has_children?
end
# Siblings
def sibling_conditions
{self.base_class.ancestry_column => read_attribute(self.base_class.ancestry_column)}
end
def siblings
self.base_class.scoped :conditions => sibling_conditions
end
def sibling_ids
siblings.all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym)
end
def has_siblings?
self.siblings.count > 1
end
def is_only_child?
!has_siblings?
end
# Descendants
def descendant_conditions
["#{self.base_class.table_name}.#{self.base_class.ancestry_column} like ? or #{self.base_class.table_name}.#{self.base_class.ancestry_column} = ?", "#{child_ancestry}/%", child_ancestry]
end
def descendants depth_options = {}
self.base_class.ordered_by_ancestry.scope_depth(depth_options, depth).scoped :conditions => descendant_conditions
end
def descendant_ids depth_options = {}
descendants(depth_options).all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym)
end
# Subtree
def subtree_conditions
["#{self.base_class.table_name}.#{self.base_class.primary_key} = ? or #{self.base_class.table_name}.#{self.base_class.ancestry_column} like ? or #{self.base_class.table_name}.#{self.base_class.ancestry_column} = ?", self.id, "#{child_ancestry}/%", child_ancestry]
end
def subtree depth_options = {}
self.base_class.ordered_by_ancestry.scope_depth(depth_options, depth).scoped :conditions => subtree_conditions
end
def subtree_ids depth_options = {}
subtree(depth_options).all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym)
end
# Callback disabling
def without_ancestry_callbacks
@disable_ancestry_callbacks = true
yield
@disable_ancestry_callbacks = false
end
def ancestry_callbacks_disabled?
!!@disable_ancestry_callbacks
end