def siblings_and_self(options = {})
      scopes        = options[:scope]         || self.default_sibling_scope
      scope_values  = options[:scope_values]  || {}

      scopes = Array.wrap(scopes).compact

      
      criteria = base_document_class.all

      detail_scopes = []

      # Find out what scope determines the root criteria. This can be 
      # [klass].all or self.[relation].
      # It is assumed that for `scopes: [:rel1, :rel2]`, sibling objects always
      # have the same `rel1` *and* `rel2`, and that two objects with the same
      # `rel1` will always have the same `rel2`.
      scopes.reverse_each do |scope|
        scope_value = scope_values.fetch(scope) { self.send(scope) }
        
        relation_metadata = self.reflect_on_association(scope)
        if relation_metadata && scope_value
          proxy = self.siblings_through_relation(scope, scope_value)
          if proxy
            criteria = proxy.criteria
            next
          end  
        end

        detail_scopes << scope
      end

      # Apply detail criteria, to make sure siblings share every simple 
      # attribute or nil-relation. 
      detail_scopes.each do |scope|
        scope_value = scope_values.fetch(scope) { self.send(scope) }

        relation_metadata = self.reflect_on_association(scope)
        if relation_metadata
          criteria = criteria.where(relation_metadata.key => scope_value)

          if scope_value && relation_metadata.polymorphic?
            type        = scope_value.class.name
            inverse_of  = send(relation_metadata.inverse_of_field) 
            
            criteria = criteria.where(relation_metadata.inverse_type      => type)
            criteria = criteria.any_in(relation_metadata.inverse_of_field => [inverse_of, nil])
          end
        else
          criteria = criteria.where(scope => scope_value)
        end
      end

      criteria
    end
def siblings_and_self(options = {})
      scopes        = options[:scope]         || self.default_sibling_scope
      scope_values  = options[:scope_values]  || {}

      scopes = Array.wrap(scopes).compact

      
      criteria = base_document_class.all

      detail_scopes = []

      # Find out what scope determines the root criteria. This can be 
      # [klass].all or self.[relation].
      # It is assumed that for `scopes: [:rel1, :rel2]`, sibling objects always
      # have the same `rel1` *and* `rel2`, and that two objects with the same
      # `rel1` will always have the same `rel2`.
      scopes.reverse_each do |scope|
        scope_value = scope_values.fetch(scope) { self.send(scope) }
        
        relation_metadata = self.reflect_on_association(scope)
        if relation_metadata && scope_value
          proxy = self.siblings_through_relation(scope, scope_value)
          if proxy
            criteria = proxy.criteria
            next
          end  
        end

        detail_scopes << scope
      end

      # Apply detail criteria, to make sure siblings share every simple 
      # attribute or nil-relation. 
      detail_scopes.each do |scope|
        scope_value = scope_values.fetch(scope) { self.send(scope) }

        relation_metadata = self.reflect_on_association(scope)
        if relation_metadata
          criteria = criteria.where(relation_metadata.key => scope_value)

          if scope_value && relation_metadata.polymorphic?
            type        = scope_value.class.name
            inverse_of  = send(relation_metadata.inverse_of_field) 
            
            criteria = criteria.where(relation_metadata.inverse_type      => type)
            criteria = criteria.any_in(relation_metadata.inverse_of_field => [inverse_of, nil])
          end
        else
          criteria = criteria.where(scope => scope_value)
        end
      end

      criteria
    end
Returns this document's siblings and itself.

 @example Retrieve document's siblings and itself within a certain scope.
   book.siblings_and_self(scope: :author)

 @example Retrieve what would be document's siblings if it had another scope value.

   book.siblings_and_self(
     scope:        :author,
     scope_values: {
       author: other_author
     }
   )

 @param [ Hash ] options The options.

 @option options [ Array<Symbol>, Symbol ] scope One or more relations or
   attributes that siblings of this object need to have in common.
 @option options [ Hash<Symbol, Object> ] scope_values Optional alternative
   values to use to determine siblingship.

 @return [ Mongoid::Criteria ] Criteria to retrieve the document's siblings.