# File lib/ancestry/instance_methods.rb, line 299 def primary_key_type @primary_key_type ||= column_for_attribute(self.class.primary_key).type end
module Ancestry::InstanceMethods
Public Instance Methods
ancestor_conditions()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 104 def ancestor_conditions self.ancestry_base_class.ancestor_conditions(self) end
ancestor_ids()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 100 def ancestor_ids parse_ancestry_column(read_attribute(self.ancestry_base_class.ancestry_column)) end
ancestor_ids_was()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 116 def ancestor_ids_was parse_ancestry_column(send("#{self.ancestry_base_class.ancestry_column}_was")) end
ancestor_of?(node)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 140 def ancestor_of?(node) node.ancestor_ids.include?(self.id) end
ancestor_was_conditions()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 112 def ancestor_was_conditions {primary_key_with_table => ancestor_ids_was} end
ancestors(depth_options = {})
click to toggle source
# File lib/ancestry/instance_methods.rb, line 108 def ancestors depth_options = {} self.ancestry_base_class.scope_depth(depth_options, depth).ordered_by_ancestry.where ancestor_conditions end
ancestors?()
click to toggle source
Ancestors
# File lib/ancestry/instance_methods.rb, line 86 def ancestors? # ancestor_ids.present? read_attribute(self.ancestry_base_class.ancestry_column).present? end
Also aliased as: has_parent?
ancestry_callbacks_disabled?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 285 def ancestry_callbacks_disabled? defined?(@disable_ancestry_callbacks) && @disable_ancestry_callbacks end
ancestry_changed?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 92 def ancestry_changed? changed.include?(self.ancestry_base_class.ancestry_column.to_s) end
ancestry_exclude_self()
click to toggle source
Validate that the ancestors don't include itself
# File lib/ancestry/instance_methods.rb, line 4 def ancestry_exclude_self errors.add(:base, "#{self.class.name.humanize} cannot be a descendant of itself.") if ancestor_ids.include? self.id end
apply_orphan_strategy()
click to toggle source
Apply orphan strategy
# File lib/ancestry/instance_methods.rb, line 29 def apply_orphan_strategy if !ancestry_callbacks_disabled? && !new_record? case self.ancestry_base_class.orphan_strategy when :rootify # make all children root if orphan strategy is rootify unscoped_descendants.each do |descendant| descendant.without_ancestry_callbacks do new_ancestry = if descendant.ancestry == child_ancestry nil else descendant.ancestry.gsub(/^#{child_ancestry}\//, '') end descendant.update_attribute descendant.class.ancestry_column, new_ancestry end end when :destroy # destroy all descendants if orphan strategy is destroy unscoped_descendants.each do |descendant| descendant.without_ancestry_callbacks do descendant.destroy end end when :adopt # make child elements of this node, child of its parent descendants.each do |descendant| descendant.without_ancestry_callbacks do new_ancestry = descendant.ancestor_ids.delete_if { |x| x == self.id }.join("/") # check for empty string if it's then set to nil new_ancestry = nil if new_ancestry.empty? descendant.update_attribute descendant.class.ancestry_column, new_ancestry || nil end end when :restrict # throw an exception if it has children raise Ancestry::AncestryException.new('Cannot delete record because it has descendants.') unless is_childless? end end end
cache_depth()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 136 def cache_depth write_attribute self.ancestry_base_class.depth_cache_column, depth end
child_ancestry()
click to toggle source
The ancestry value for this record's children
# File lib/ancestry/instance_methods.rb, line 77 def child_ancestry # New records cannot have children raise Ancestry::AncestryException.new('No child ancestry for new record. Save record before performing tree operations.') if new_record? if self.send("#{self.ancestry_base_class.ancestry_column}_was").blank? then id.to_s else "#{self.send "#{self.ancestry_base_class.ancestry_column}_was"}/#{id}" end end
child_conditions()
click to toggle source
Children
# File lib/ancestry/instance_methods.rb, line 191 def child_conditions self.ancestry_base_class.child_conditions(self) end
child_ids()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 199 def child_ids children.pluck(self.ancestry_base_class.primary_key) end
child_of?(node)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 213 def child_of?(node) self.parent_id == node.id end
children()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 195 def children self.ancestry_base_class.where child_conditions end
depth()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 132 def depth ancestor_ids.size end
descendant_conditions()
click to toggle source
Descendants
# File lib/ancestry/instance_methods.rb, line 247 def descendant_conditions self.ancestry_base_class.descendant_conditions(self) end
descendant_ids(depth_options = {})
click to toggle source
# File lib/ancestry/instance_methods.rb, line 255 def descendant_ids depth_options = {} descendants(depth_options).pluck(self.ancestry_base_class.primary_key) end
descendant_of?(node)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 259 def descendant_of?(node) ancestor_ids.include?(node.id) end
descendants(depth_options = {})
click to toggle source
# File lib/ancestry/instance_methods.rb, line 251 def descendants depth_options = {} self.ancestry_base_class.ordered_by_ancestry.scope_depth(depth_options, depth).where descendant_conditions end
has_children?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 203 def has_children? self.children.exists? end
Also aliased as: children?
has_siblings?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 231 def has_siblings? self.siblings.count > 1 end
Also aliased as: siblings?
is_childless?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 208 def is_childless? !has_children? end
Also aliased as: childless?
is_only_child?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 236 def is_only_child? !has_siblings? end
Also aliased as: only_child?
is_root?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 180 def is_root? read_attribute(self.ancestry_base_class.ancestry_column).blank? end
Also aliased as: root?
parent()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 158 def parent unscoped_find(parent_id) if ancestors? end
parent=(parent)
click to toggle source
Parent
# File lib/ancestry/instance_methods.rb, line 146 def parent= parent write_attribute(self.ancestry_base_class.ancestry_column, if parent.nil? then nil else parent.child_ancestry end) end
parent_id()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 154 def parent_id ancestor_ids.last if ancestors? end
parent_id=(new_parent_id)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 150 def parent_id= new_parent_id self.parent = new_parent_id.present? ? unscoped_find(new_parent_id) : nil end
parent_id?()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 162 def parent_id? ancestors? end
parent_of?(node)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 166 def parent_of?(node) self.id == node.parent_id end
parse_ancestry_column(obj)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 96 def parse_ancestry_column obj obj.to_s.split('/').map { |id| cast_primary_key(id) } end
path(depth_options = {})
click to toggle source
# File lib/ancestry/instance_methods.rb, line 128 def path depth_options = {} self.ancestry_base_class.scope_depth(depth_options, depth).ordered_by_ancestry.where path_conditions end
path_conditions()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 124 def path_conditions self.ancestry_base_class.path_conditions(self) end
path_ids()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 120 def path_ids ancestor_ids + [id] end
root()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 176 def root ancestors? ? unscoped_find(root_id) : self end
root_id()
click to toggle source
Root
# File lib/ancestry/instance_methods.rb, line 172 def root_id ancestors? ? ancestor_ids.first : id end
root_of?(node)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 185 def root_of?(node) self.id == node.root_id end
sibling_conditions()
click to toggle source
Siblings
# File lib/ancestry/instance_methods.rb, line 219 def sibling_conditions self.ancestry_base_class.sibling_conditions(self) end
sibling_ids()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 227 def sibling_ids siblings.pluck(self.ancestry_base_class.primary_key) end
sibling_of?(node)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 241 def sibling_of?(node) self.ancestry == node.ancestry end
siblings()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 223 def siblings self.ancestry_base_class.where sibling_conditions end
subtree(depth_options = {})
click to toggle source
# File lib/ancestry/instance_methods.rb, line 269 def subtree depth_options = {} self.ancestry_base_class.ordered_by_ancestry.scope_depth(depth_options, depth).where subtree_conditions end
subtree_conditions()
click to toggle source
Subtree
# File lib/ancestry/instance_methods.rb, line 265 def subtree_conditions self.ancestry_base_class.subtree_conditions(self) end
subtree_ids(depth_options = {})
click to toggle source
# File lib/ancestry/instance_methods.rb, line 273 def subtree_ids depth_options = {} subtree(depth_options).pluck(self.ancestry_base_class.primary_key) end
touch_ancestors_callback()
click to toggle source
Touch each of this record's ancestors
# File lib/ancestry/instance_methods.rb, line 65 def touch_ancestors_callback if !ancestry_callbacks_disabled? && self.ancestry_base_class.touch_ancestors # Touch each of the old *and* new ancestors unscoped_current_and_previous_ancestors.each do |ancestor| ancestor.without_ancestry_callbacks do ancestor.touch end end end end
update_descendants_with_new_ancestry()
click to toggle source
Update descendants with new ancestry
# File lib/ancestry/instance_methods.rb, line 9 def update_descendants_with_new_ancestry # If enabled and node is existing and ancestry was updated and the new ancestry is sane ... if !ancestry_callbacks_disabled? && !new_record? && ancestry_changed? && sane_ancestry? # ... for each descendant ... unscoped_descendants.each do |descendant| # ... replace old ancestry with new ancestry descendant.without_ancestry_callbacks do descendant.update_attribute( self.ancestry_base_class.ancestry_column, descendant.read_attribute(descendant.class.ancestry_column).gsub( /^#{self.child_ancestry}/, if ancestors? then "#{read_attribute self.class.ancestry_column }/#{id}" else id.to_s end ) ) end end end end
without_ancestry_callbacks() { || ... }
click to toggle source
Callback disabling
# File lib/ancestry/instance_methods.rb, line 279 def without_ancestry_callbacks @disable_ancestry_callbacks = true yield @disable_ancestry_callbacks = false end
Private Instance Methods
cast_primary_key(key)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 291 def cast_primary_key(key) if [:string, :uuid, :text].include? primary_key_type key else key.to_i end end
primary_key_type()
click to toggle source
unscoped_current_and_previous_ancestors()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 309 def unscoped_current_and_previous_ancestors unscoped_where do |scope| scope.where id: (ancestor_ids + ancestor_ids_was).uniq end end
unscoped_descendants()
click to toggle source
# File lib/ancestry/instance_methods.rb, line 303 def unscoped_descendants unscoped_where do |scope| scope.where descendant_conditions end end
unscoped_find(id)
click to toggle source
# File lib/ancestry/instance_methods.rb, line 315 def unscoped_find id unscoped_where do |scope| scope.find id end end
unscoped_where() { |scope| ... }
click to toggle source
# File lib/ancestry/instance_methods.rb, line 321 def unscoped_where self.ancestry_base_class.unscoped_where do |scope| yield scope end end