# File lib/ancestry/instance_methods.rb, line 72 def ancestor_conditions {self.base_class.primary_key => ancestor_ids} end
Ancestors
# File lib/ancestry/instance_methods.rb, line 68 def ancestor_ids read_attribute(self.base_class.ancestry_column).to_s.split('/').map { |id| cast_primary_key(id) } end
# File lib/ancestry/instance_methods.rb, line 76 def ancestors depth_options = {} self.base_class.scope_depth(depth_options, depth).ordered_by_ancestry.scoped :conditions => ancestor_conditions end
# File lib/ancestry/instance_methods.rb, line 205 def ancestry_callbacks_disabled? !!@disable_ancestry_callbacks end
Validate that the ancestors don't include itself
# File lib/ancestry/instance_methods.rb, line 4 def ancestry_exclude_self add_error_to_base "#{self.class.name.humanize} cannot be a descendant of itself." if ancestor_ids.include? self.id end
Apply orphan strategy
# File lib/ancestry/instance_methods.rb, line 32 def apply_orphan_strategy # Skip this if callbacks are disabled unless ancestry_callbacks_disabled? # If this isn't a new record ... unless new_record? # ... make all children root if orphan strategy is rootify if self.base_class.orphan_strategy == :rootify unscoped_descendants.each do |descendant| descendant.without_ancestry_callbacks do descendant.update_attribute descendant.class.ancestry_column, (if descendant.ancestry == child_ancestry then nil else descendant.ancestry.gsub(/^#{child_ancestry}\//, '') end) end end # ... destroy all descendants if orphan strategy is destroy elsif self.base_class.orphan_strategy == :destroy unscoped_descendants.each do |descendant| descendant.without_ancestry_callbacks do descendant.destroy end end # ... throw an exception if it has children and orphan strategy is restrict elsif self.base_class.orphan_strategy == :restrict raise Ancestry::AncestryException.new('Cannot delete record because it has descendants.') unless is_childless? end end end end
# File lib/ancestry/instance_methods.rb, line 96 def cache_depth write_attribute self.base_class.depth_cache_column, depth end
The ancestry value for this record's children
# File lib/ancestry/instance_methods.rb, line 60 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.base_class.ancestry_column}_was").blank? then id.to_s else "#{self.send "#{self.base_class.ancestry_column}_was"}/#{id}" end end
Children
# File lib/ancestry/instance_methods.rb, line 131 def child_conditions {self.base_class.ancestry_column => child_ancestry} end
# File lib/ancestry/instance_methods.rb, line 139 def child_ids children.all(:select => self.base_class.primary_key).map(&self.base_class.primary_key.to_sym) end
# File lib/ancestry/instance_methods.rb, line 135 def children self.base_class.scoped :conditions => child_conditions end
# File lib/ancestry/instance_methods.rb, line 92 def depth ancestor_ids.size end
Descendants
# File lib/ancestry/instance_methods.rb, line 173 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
# File lib/ancestry/instance_methods.rb, line 181 def descendant_ids depth_options = {} descendants(depth_options).all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym) end
# File lib/ancestry/instance_methods.rb, line 177 def descendants depth_options = {} self.base_class.ordered_by_ancestry.scope_depth(depth_options, depth).scoped :conditions => descendant_conditions end
# File lib/ancestry/instance_methods.rb, line 143 def has_children? self.children.exists?({}) end
# File lib/ancestry/instance_methods.rb, line 164 def has_siblings? self.siblings.count > 1 end
# File lib/ancestry/instance_methods.rb, line 147 def is_childless? !has_children? end
# File lib/ancestry/instance_methods.rb, line 168 def is_only_child? !has_siblings? end
# File lib/ancestry/instance_methods.rb, line 126 def is_root? read_attribute(self.base_class.ancestry_column).blank? end
# File lib/ancestry/instance_methods.rb, line 113 def parent if parent_id.blank? then nil else self.base_class.find(parent_id) end end
Parent
# File lib/ancestry/instance_methods.rb, line 101 def parent= parent write_attribute(self.base_class.ancestry_column, if parent.blank? then nil else parent.child_ancestry end) end
# File lib/ancestry/instance_methods.rb, line 109 def parent_id if ancestor_ids.empty? then nil else ancestor_ids.last end end
# File lib/ancestry/instance_methods.rb, line 105 def parent_id= parent_id self.parent = if parent_id.blank? then nil else self.base_class.find(parent_id) end end
# File lib/ancestry/instance_methods.rb, line 88 def path depth_options = {} self.base_class.scope_depth(depth_options, depth).ordered_by_ancestry.scoped :conditions => path_conditions end
# File lib/ancestry/instance_methods.rb, line 84 def path_conditions {self.base_class.primary_key => path_ids} end
# File lib/ancestry/instance_methods.rb, line 80 def path_ids ancestor_ids + [id] end
# File lib/ancestry/instance_methods.rb, line 122 def root if root_id == id then self else self.base_class.find(root_id) end end
Root
# File lib/ancestry/instance_methods.rb, line 118 def root_id if ancestor_ids.empty? then id else ancestor_ids.first end end
Siblings
# File lib/ancestry/instance_methods.rb, line 152 def sibling_conditions {self.base_class.ancestry_column => read_attribute(self.base_class.ancestry_column)} end
# File lib/ancestry/instance_methods.rb, line 160 def sibling_ids siblings.all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym) end
# File lib/ancestry/instance_methods.rb, line 156 def siblings self.base_class.scoped :conditions => sibling_conditions end
# File lib/ancestry/instance_methods.rb, line 190 def subtree depth_options = {} self.base_class.ordered_by_ancestry.scope_depth(depth_options, depth).scoped :conditions => subtree_conditions end
Subtree
# File lib/ancestry/instance_methods.rb, line 186 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
# File lib/ancestry/instance_methods.rb, line 194 def subtree_ids depth_options = {} subtree(depth_options).all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym) end
Update descendants with new ancestry
# File lib/ancestry/instance_methods.rb, line 9 def update_descendants_with_new_ancestry # Skip this if callbacks are disabled unless ancestry_callbacks_disabled? # If node is valid, not a new record and ancestry was updated ... if changed.include?(self.base_class.ancestry_column.to_s) && !new_record? && valid? # ... for each descendant ... unscoped_descendants.each do |descendant| # ... replace old ancestry with new ancestry descendant.without_ancestry_callbacks do descendant.update_attribute( self.base_class.ancestry_column, descendant.read_attribute(descendant.class.ancestry_column).gsub( /^#{self.child_ancestry}/, if read_attribute(self.class.ancestry_column).blank? then id.to_s else "#{read_attribute self.class.ancestry_column }/#{id}" end ) ) end end end end end
Generated with the Darkfish Rdoc Generator 2.