ancestry

有以下 10 个类方法

# 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!

对 ActiveRecord::Base 的 两个 扩展

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

你可能感兴趣的:(ancestry)