module FastTree::Model::ClassMethods

Class Methods

Public Instance Methods

_create_parent_embedded_space(children) click to toggle source
# File lib/fast_tree/model.rb, line 60
      def _create_parent_embedded_space(children)
        left  = children.max {|c| c.l_ptr}.l_ptr
        right = children.min {|c| c.r_ptr}.r_ptr

        sql = <<-"EOS"
UPDATE #{self.to_s.underscore.pluralize}
  SET l_ptr = CASE
                WHEN l_ptr >= #{left}
                  AND r_ptr <= #{right}
                  THEN l_ptr + 1
                WHEN l_ptr > #{right}
                  THEN l_ptr + 2
                ELSE l_ptr
                END,
      r_ptr = CASE
                WHEN l_ptr >= #{left}
                  AND r_ptr <= #{right}
                  THEN r_ptr + 1
                WHEN l_ptr < #{left}
                  AND r_ptr > #{right}
                  THEN r_ptr + 2
                WHEN l_ptr > #{right}
                  THEN r_ptr + 2
                ELSE r_ptr
              END,
      depth = CASE
                WHEN l_ptr >= #{left}
                  AND r_ptr <= #{right}
                  THEN depth + 1
                ELSE depth
              END
  WHERE r_ptr > #{left}
        EOS

        ActiveRecord::Base.connection.execute(sql)

        # return left and right pointers between which parent is embedded
        {l_ptr: left, r_ptr: right + 2}
      end
add_parent(parent, children, &block) click to toggle source

structure operation

# File lib/fast_tree/model.rb, line 20
def add_parent(parent, children, &block)
  parent_depth = children.first.depth

  # create space for parent
  ptrs = _create_parent_embedded_space(children)

  # parent node's pointer
  parent.l_ptr = ptrs[:l_ptr]
  parent.r_ptr = ptrs[:r_ptr]
  parent.depth = parent_depth
  parent.save
end
create_parent(attributes = {}, children, &block) click to toggle source
# File lib/fast_tree/model.rb, line 33
def create_parent(attributes = {}, children, &block)
  parent_depth = children.first.depth

  # create space for parent
  ptrs = _create_parent_embedded_space(children)

  # parent node's pointer
  attributes[:l_ptr] = ptrs[:l_ptr]
  attributes[:r_ptr] = ptrs[:r_ptr]
  attributes[:depth] = parent_depth

  self.create(attributes, &block)
end
create_tree(attributes={}, &block) click to toggle source
# File lib/fast_tree/model.rb, line 47
def create_tree(attributes={}, &block)
  root = self.find_root
  if root
    root
  else
    attributes[:l_ptr] = 0
    attributes[:r_ptr] = 1
    attributes[:depth] = 0
    self.create(attributes, &block)
  end
end
find_root() click to toggle source

model operation

# File lib/fast_tree/model.rb, line 104
def find_root
  self.find_by(l_ptr: 0)
end
find_subtree_by_root(node) click to toggle source
# File lib/fast_tree/model.rb, line 108
def find_subtree_by_root(node)
  l_ptr = node.l_ptr
  r_ptr = node.r_ptr

  self.where(self.arel_table[:l_ptr].gteq(l_ptr))
      .where(self.arel_table[:r_ptr].lteq(r_ptr))
end
print_subtree(root) click to toggle source

for debugging