module Mongoid::SleepingKingStudios::HasTree

Adds a belongs_to parent relation and a has_many children relation to set up a basic tree structure, as well as several helper methods.

@note From 0.2.0 to 0.3.1, was Mongoid::SleepingKingStudios::Tree.

@example Setting up the tree:

class SluggableDocument
  include Mongoid::Document
  include Mongoid::SleepingKingStudios::Tree

  has_tree
end # class

Since 0.4.1, you must call the class method ::has_tree in order to set up the parent and children relations. You can pass optional parameters into this method to customise the created relations, including the names of the relations.

@example Setting up the tree with alternate relation names:

class EvilEmployee
  include Mongoid::Document
  include Mongoid::SleepingKingStudios::Tree

  has_tree :parent => { :relation_name => 'overlord' },
    :children => { :relation_name => 'minions', :dependent => :destroy }
end # class

@since 0.2.0

Public Class Methods

apply(base, options) click to toggle source

@api private

Sets up the has_tree relation, creating fields, accessors and validations.

@param [Class] base The base class into which the concern is mixed in. @param [Hash] options The options for the relation.

@since 0.6.0

# File lib/mongoid/sleeping_king_studios/has_tree.rb, line 50
def self.apply base, options
  options[:parent]   ||= {}
  options[:children] ||= {}

  options[:parent][:inverse_of]   = options[:children].fetch(:relation_name, :children)
  options[:children][:inverse_of] = options[:parent].fetch(:relation_name,   :parent)

  name = :has_tree
  validate_options    name, options
  meta = characterize name, options, Metadata

  relate base, name, meta

  define_relations base, meta
  define_helpers   base, meta

  if meta.cache_ancestry?
    concern = Mongoid::SleepingKingStudios::HasTree::CacheAncestry
    concern.send :apply, base, meta.cache_ancestry
  end # if
end
define_helpers(base, metadata) click to toggle source

@api private

Sets up the helper methods for the relations as follows.

Defines the following class methods:

  • ::roots

Defines the following instance methods:

  • leaf?

  • root

  • root?

@param [Class] base The base class into which the concern is mixed in. @param [Metadata] metadata The metadata for the relation.

@since 0.6.0

# File lib/mongoid/sleeping_king_studios/has_tree.rb, line 88
def self.define_helpers base, metadata
  base.metaclass.send :define_method, :roots do
    where({ :"#{metadata.parent.relation_name}_id" => nil })
  end # class method roots

  base.send :define_method, :root do
    parent = send(metadata.parent.relation_name)
    parent ? parent.root : self
  end # method root

  base.send :define_method, :leaf? do
    send(metadata.children.relation_name).blank?
  end # method root?

  base.send :define_method, :root? do
    send(metadata.parent.relation_name).nil?
  end # method root?

  base.send :define_method, :siblings do
    self.class.where(:id => { "$ne" => self.id }).where(metadata.foreign_key => self.send(metadata.foreign_key))
  end # method siblings
end
define_relations(base, metadata) click to toggle source

@api private

Sets up the parent and children relations.

@param [Class] base The base class into which the concern is mixed in. @param [Metadata] metadata The metadata for the relation.

@since 0.6.0

# File lib/mongoid/sleeping_king_studios/has_tree.rb, line 119
def self.define_relations base, metadata
  parent_options = metadata.parent.properties.dup
  parent_options.update :class_name => base.name
  parent_options.delete :relation_name

  children_options = metadata.children.properties.dup
  children_options.update :class_name => base.name
  children_options.delete :relation_name

  base.belongs_to metadata.parent.relation_name,   parent_options
  base.has_many   metadata.children.relation_name, children_options
end
valid_options() click to toggle source

Get the valid options allowed with this concern.

@return [ Array<Symbol> ] The valid options.

@since 0.4.1

# File lib/mongoid/sleeping_king_studios/has_tree.rb, line 137
def self.valid_options
  %i(
    cache_ancestry
    children
    parent
  ) # end Array
end