/usr/lib/ruby/vendor_ruby/sequel/plugins/tree.rb is in ruby-sequel 3.33.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | module Sequel
module Plugins
# The Tree plugin adds additional associations and methods that allow you to
# treat a Model as a tree.
#
# A column for holding the parent key is required and is :parent_id by default.
# This may be overridden by passing column name via :key
#
# Optionally, a column to control order of nodes returned can be specified
# by passing column name via :order.
#
# If you pass true for the :single_root option, the class will ensure there is
# only ever one root in the tree.
#
# Examples:
#
# class Node < Sequel::Model
# plugin :tree
# end
#
# class Node < Sequel::Model
# plugin :tree, :key=>:parentid, :order=>:position
# end
module Tree
# Create parent and children associations. Any options
# specified are passed to both associations. You can
# specify options to use for the parent association
# using a :parent option, and options to use for the
# children association using a :children option.
def self.apply(model, opts={})
opts = opts.dup
opts[:class] = model
model.instance_eval do
@parent_column = (opts[:key] ||= :parent_id)
@tree_order = opts[:order]
end
par = opts.merge(opts.fetch(:parent, {}))
parent = par.fetch(:name, :parent)
model.many_to_one parent, par
chi = opts.merge(opts.fetch(:children, {}))
children = chi.fetch(:name, :children)
model.one_to_many children, chi
model.plugin SingleRoot if opts[:single_root]
end
module ClassMethods
# The column symbol or array of column symbols on which to order the tree.
attr_accessor :tree_order
# The symbol for the column containing the value pointing to the
# parent of the leaf.
attr_accessor :parent_column
# Copy the +parent_column+ and +order_column+ to the subclass.
def inherited(subclass)
super
subclass.parent_column = parent_column
subclass.tree_order = tree_order
end
# Returns list of all root nodes (those with no parent nodes).
#
# TreeClass.roots # => [root1, root2]
def roots
roots_dataset.all
end
# Returns the dataset for retrieval of all root nodes
#
# TreeClass.roots_dataset => Sequel#Dataset
def roots_dataset
ds = filter(parent_column => nil)
ds = ds.order(*tree_order) if tree_order
ds
end
end
module InstanceMethods
# Returns list of ancestors, starting from parent until root.
#
# subchild1.ancestors # => [child1, root]
def ancestors
node, nodes = self, []
nodes << node = node.parent while node.parent
nodes
end
# Returns list of ancestors, starting from parent until root.
#
# subchild1.ancestors # => [child1, root]
def descendants
nodes = children.dup
nodes.each{|child| nodes.concat(child.descendants)}
nodes
end
# Returns the root node of the tree that this node descends from
# This node is returned if it is a root node itself.
def root
ancestors.last || self
end
# Returns true if this is a root node, false otherwise.
def root?
!new? && self[model.parent_column].nil?
end
# Returns all siblings and a reference to the current node.
#
# subchild1.self_and_siblings # => [subchild1, subchild2]
def self_and_siblings
parent ? parent.children : model.roots
end
# Returns all siblings of the current node.
#
# subchild1.siblings # => [subchild2]
def siblings
self_and_siblings - [self]
end
end
# Plugin included when :single_root option is passed
module SingleRoot
module ClassMethods
# Returns the single root node.
def root
roots_dataset.first
end
end
module InstanceMethods
# Hook that prevents a second root from being created.
def before_save
if self[model.parent_column].nil? && (root = model.root) && pk != root.pk
raise TreeMultipleRootError, "there is already a root #{model.name} defined"
end
super
end
end
end
class TreeMultipleRootError < Error; end
end
end
end
|