Module: ActsAsSaneTree::InstanceMethods

Defined in:
lib/acts_as_sane_tree/instance_methods.rb

Instance Method Summary collapse

Instance Method Details

#ancestorsObject

Returns all ancestors of the current node.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 5

def ancestors
  query = 
    "(WITH RECURSIVE crumbs AS (
      SELECT #{self.class.configuration[:class].table_name}.*,
      1 AS depth
      FROM #{self.class.configuration[:class].table_name}
      WHERE id = #{id} 
      UNION ALL
      SELECT alias1.*, 
      depth + 1 
      FROM crumbs
      JOIN #{self.class.configuration[:class].table_name} alias1 ON alias1.id = crumbs.parent_id
    ) SELECT * FROM crumbs WHERE crumbs.id != #{id}) as #{self.class.configuration[:class].table_name}"
  if(self.class.rails_3?)
    self.class.configuration[:class].send(:with_exclusive_scope) do
      self.class.configuration[:class].from(
        query
      ).order("#{self.class.configuration[:class].table_name}.depth DESC")
    end
  else
    self.class.configuration[:class].send(:with_exclusive_scope) do
      self.class.configuration[:class].scoped(
        :from => query,
        :order => "#{self.class.configuration[:class].table_name}.depth DESC"
      )
    end
  end
end

#depthObject

Returns the depth of the current node. 0 depth represents the root of the tree



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 84

def depth
  query = 
    "WITH RECURSIVE crumbs AS (
      SELECT parent_id, 0 AS level
      FROM #{self.class.configuration[:class].table_name}
      WHERE id = #{self.id} 
      UNION ALL
      SELECT alias1.parent_id, level + 1 
      FROM crumbs
      JOIN #{self.class.configuration[:class].table_name} alias1 ON alias1.id = crumbs.parent_id
    ) SELECT level FROM crumbs ORDER BY level DESC LIMIT 1"
  ActiveRecord::Base.connection.select_all(query).first.try(:[], 'level').try(:to_i)
end

#descendants(*args) ⇒ Object Also known as: descendents

Returns all descendants of the current node. Each level is within its own hash, so for a structure like:

root
 \_ child1
      \_ subchild1
            \_ subsubchild1
      \_ subchild2

the resulting hash would look like:

{child1 => 
  {subchild1 => 
    {subsubchild1 => {}},
   subchild2 => {}}}

This method will accept two parameters.

* :raw -> Result is scope that can more finders can be chained against with additional 'level' attribute
* {:depth => n} -> Will only search for descendants to the given depth of n

NOTE: You can restrict results by depth on the scope returned, but better performance will be gained by specifying it within the args so it will be applied during the recursion, not after.



77
78
79
80
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 77

def descendants(*args)
  args.delete_if{|x| !x.is_a?(Hash) && x != :raw}
  self.class.configuration[:class].nodes_and_descendants(:no_self, self, *args)
end

#rootObject

Returns the root node of the tree.



35
36
37
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 35

def root
  ancestors.first
end

#root?Boolean

Returns if the current node is a root

Returns:

  • (Boolean)


54
55
56
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 54

def root?
  parent_id.nil?
end

#self_and_siblingsObject

Returns all siblings and a reference to the current node.

subchild1.self_and_siblings # => [subchild1, subchild2]


49
50
51
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 49

def self_and_siblings
  parent ? parent.children : self.class.configuration[:class].roots
end

#siblingsObject

Returns all siblings of the current node.

subchild1.siblings # => [subchild2]


42
43
44
# File 'lib/acts_as_sane_tree/instance_methods.rb', line 42

def siblings
  self_and_siblings - [self]
end