lib/mongoid_nested_set/base.rb
def acts_as_nested_set(options = {})
      options = {
        :parent_field => 'parent_id',
        :left_field => 'lft',
        :right_field => 'rgt',
        :outline_number_field => nil,
        :dependent => :delete_all, # or :destroy
        :klass => self,
      }.merge(options)

      if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
        options[:scope] = "#{options[:scope]}_id".intern
      end

      class_attribute :acts_as_nested_set_options, :instance_writer => false
      self.acts_as_nested_set_options = options

      unless self.is_a?(Document::ClassMethods)
        include Document
        include OutlineNumber if outline_number_field_name

        field left_field_name, :type => Integer
        field right_field_name, :type => Integer
        field outline_number_field_name, :type => String if outline_number_field_name
        field :depth, :type => Integer

        has_many   :children, :class_name => self.name, :foreign_key => parent_field_name, :inverse_of => :parent, :order => left_field_name.to_sym.asc
        belongs_to :parent,   :class_name => self.name, :foreign_key => parent_field_name

        attr_accessor :skip_before_destroy

        if accessible_attributes.blank?
          attr_protected left_field_name.intern, right_field_name.intern
        end

        define_callbacks :move, :terminator => "result == false"

        before_create  :set_default_left_and_right
        before_save    :store_new_parent
        after_save     :move_to_new_parent
        before_destroy :destroy_descendants

        # no assignment to structure fields
        [left_field_name, right_field_name].each do |field|
          module_eval <<-"end_eval", __FILE__, __LINE__
                  def #{field}=(x)
                    raise NameError, "Unauthorized assignment to #{field}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead.", "#{field}"
                  end
          end_eval
        end

        scope :roots, lambda {
          where(parent_field_name => nil).asc(left_field_name)
        }
        scope :leaves, lambda {
          where("this.#{quoted_right_field_name} - this.#{quoted_left_field_name} == 1").asc(left_field_name)
        }
        scope :with_depth, lambda { |level|
          where(:depth => level).asc(left_field_name)
        }

      end
    end
def acts_as_nested_set(options = {})
      options = {
        :parent_field => 'parent_id',
        :left_field => 'lft',
        :right_field => 'rgt',
        :outline_number_field => nil,
        :dependent => :delete_all, # or :destroy
        :klass => self,
      }.merge(options)

      if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
        options[:scope] = "#{options[:scope]}_id".intern
      end

      class_attribute :acts_as_nested_set_options, :instance_writer => false
      self.acts_as_nested_set_options = options

      unless self.is_a?(Document::ClassMethods)
        include Document
        include OutlineNumber if outline_number_field_name

        field left_field_name, :type => Integer
        field right_field_name, :type => Integer
        field outline_number_field_name, :type => String if outline_number_field_name
        field :depth, :type => Integer

        has_many   :children, :class_name => self.name, :foreign_key => parent_field_name, :inverse_of => :parent, :order => left_field_name.to_sym.asc
        belongs_to :parent,   :class_name => self.name, :foreign_key => parent_field_name

        attr_accessor :skip_before_destroy

        if accessible_attributes.blank?
          attr_protected left_field_name.intern, right_field_name.intern
        end

        define_callbacks :move, :terminator => "result == false"

        before_create  :set_default_left_and_right
        before_save    :store_new_parent
        after_save     :move_to_new_parent
        before_destroy :destroy_descendants

        # no assignment to structure fields
        [left_field_name, right_field_name].each do |field|
          module_eval <<-"end_eval", __FILE__, __LINE__
                  def #{field}=(x)
                    raise NameError, "Unauthorized assignment to #{field}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead.", "#{field}"
                  end
          end_eval
        end

        scope :roots, lambda {
          where(parent_field_name => nil).asc(left_field_name)
        }
        scope :leaves, lambda {
          where("this.#{quoted_right_field_name} - this.#{quoted_left_field_name} == 1").asc(left_field_name)
        }
        scope :with_depth, lambda { |level|
          where(:depth => level).asc(left_field_name)
        }

      end
    end
def acts_as_nested_set ( options = { } ) options = { :parent_field => 'parent_id' , :left_field => 'lft' , :right_field => 'rgt' , :outline_number_field => nil , :dependent => :delete_all , # or :destroy :klass => self , } . merge ( options ) if options [ :scope ] . is_a? ( Symbol ) && options [ :scope ] . to_s !~ / / options [ :scope ] = "#{options[:scope]}_id" . intern end class_attribute :acts_as_nested_set_options , :instance_writer => false self . acts_as_nested_set_options = options unless self . is_a? ( Document :: ClassMethods ) include Document include OutlineNumber if outline_number_field_name field left_field_name , :type => Integer field right_field_name , :type => Integer field outline_number_field_name , :type => String if outline_number_field_name field :depth , :type => Integer has_many :children , :class_name => self . name , :foreign_key => parent_field_name , :inverse_of => :parent , :order => left_field_name . to_sym . asc belongs_to :parent , :class_name => self . name , :foreign_key => parent_field_name attr_accessor :skip_before_destroy if accessible_attributes . blank? attr_protected left_field_name . intern , right_field_name . intern end define_callbacks :move , :terminator => "result == false" before_create :set_default_left_and_right before_save :store_new_parent after_save :move_to_new_parent before_destroy :destroy_descendants # no assignment to structure fields [ left_field_name , right_field_name ] . each do | field | module_eval <<-"end_eval" , __FILE__ , __LINE__ #{ field } #{ field } #{ field } end_eval end scope :roots , lambda { where ( parent_field_name => nil ) . asc ( left_field_name ) } scope :leaves , lambda { where ( "this.#{quoted_right_field_name} - this.#{quoted_left_field_name} == 1" ) . asc ( left_field_name ) } scope :with_depth , lambda { | level | where ( :depth => level ) . asc ( left_field_name ) } end end
Configuration options are:

 * +:parent_field+ - field name to use for keeping the parent id (default: parent_id)
 * +:left_field+ - field name for left boundary data, default 'lft'
 * +:right_field+ - field name for right boundary data, default 'rgt'
 * +:outline_number_field+ - field name for the number field, default nil.  If set,
   the value will be used as a field name to keep track of each node's
   "outline number" (e.g. 1.2.5).
 * +:scope+ - restricts what is to be considered a list.  Given a symbol, it'll attach
   "_id" (if it hasn't been already) and use that as the foreign key restriction.  You
   can also pass an array to scope by multiple attributes
 * +:dependent+ - behavior for cascading destroy.  If set to :destroy, all the child
   objects are destroyed alongside this object by calling their destroy method.  If set
   to :delete_all (default), all the child objects are deleted without calling their
   destroy method.
 * +:klass+ - class to use for queries (defaults to self)

 See Mongoid::Acts::NestedSet::ClassMethods for a list of class methods and
 Mongoid::Acts::NestedSet::InstanceMethods for a list of instance methods added to
 acts_as_nested_set models
Configuration options are :