module Mongestry::InstanceMethods
Public Class Methods
# File lib/mongestry.rb, line 15 def self.included base base.extend Mongestry::ClassMethods end
Public Instance Methods
Returns a list of ancestor ids, starting with the root id and ending with the parent id
# File lib/mongestry.rb, line 34 def ancestor_ids self.ancestry.split('/').collect{ |s| BSON::ObjectId.from_string s } end
Scopes the model on ancestors of the record
# File lib/mongestry.rb, line 39 def ancestors return [] if self.is_root? self.class.where(_id: {"$in" => self.ancestor_ids}) end
# File lib/mongestry.rb, line 19 def build_ancestry raise "Either parent or parent_id can be given, not both at once" if self.attributes.keys.include?("parent") and self.attributes.keys.include?("parent_id") return unless self.respond_to?(:parent) or self.respond_to?(:parent_id) parent = self.class.object_for(self.attributes["parent"] || self.attributes["parent_id"]) self.ancestry = nil unless parent self.ancestry = parent.ancestry.nil? ? parent.id.to_s : parent.ancestry.to_s + "/#{parent.id.to_s}" if parent self.persisted_depth = parent.depth + 1 rescue 0 self.attributes.delete("parent") self.attributes.delete("parent_id") end
Returns a list of child ids
# File lib/mongestry.rb, line 81 def child_ids self.children.map(&:id) end
Scopes the model on children of the record
# File lib/mongestry.rb, line 71 def children case self.is_root? when true self.class.where(:ancestry => self.ancestry.to_s + "#{self.id.to_s}") else self.class.where(:ancestry => self.ancestry.to_s + "/#{self.id.to_s}") end end
Return the depth of the node, root nodes are at depth 0
# File lib/mongestry.rb, line 137 def depth self.ancestry.split('/').size rescue 0 end
Returns a list of a descendant ids
# File lib/mongestry.rb, line 122 def descendant_ids self.descendants.map(&:id) end
Scopes the model on direct and indirect children of the record
# File lib/mongestry.rb, line 116 def descendants expression = self.is_root? ? self.id.to_s : (self.ancestry + "/#{self.id.to_s}").split('/').join('\/') self.class.where(:ancestry => Regexp.new(expression)) end
Returns true if the record has any children, false otherwise
# File lib/mongestry.rb, line 86 def has_children? !self.children.to_a.blank? end
Returns true if the record’s parent has more than one child
# File lib/mongestry.rb, line 106 def has_siblings? self.siblings.present? end
Returns true if the record has no childen, false otherwise
# File lib/mongestry.rb, line 91 def is_childless? !self.has_children? end
Returns true if the record is the only child of its parent
# File lib/mongestry.rb, line 111 def is_only_child? !self.has_siblings? end
Returns true if the record is a root node, false otherwise
# File lib/mongestry.rb, line 66 def is_root? self.ancestry.nil? end
Returns the parent of the record, nil for a root node
# File lib/mongestry.rb, line 45 def parent self.class.where(_id: self.ancestry.split('/').last).first rescue nil end
Returns the id of the parent of the record, nil for a root node
# File lib/mongestry.rb, line 50 def parent_id self.parent.id rescue nil end
Returns the root of the tree the record is in, self for a root node
# File lib/mongestry.rb, line 55 def root return self unless self.ancestry self.class.where(_id: self.ancestry.split('/').first).first end
Returns the id of the root of the tree the record is in
# File lib/mongestry.rb, line 61 def root_id self.root.id end
Returns a list of sibling ids
# File lib/mongestry.rb, line 101 def sibling_ids self.siblings.map(&:id) end
Scopes the model on siblings of the record, the record itself is included
# File lib/mongestry.rb, line 96 def siblings self.class.where(:ancestry => self.ancestry.to_s).and(:_id => {'$ne' => self.id}) end
Scopes the model on descendants and itself
# File lib/mongestry.rb, line 127 def subtree self.class.where(_id: {"$in" => self.descendant_ids.push(self.id)}) end
Returns a list of all ids in the record’s subtree
# File lib/mongestry.rb, line 132 def subtree_ids self.subtree.map(&:id) end