123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Scopable::ClassMethods

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Extended In:
Defined in: lib/mongoid/scopable.rb

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#default_scopable?true | false (readonly)

Is the class able to have the default scope applied?

Examples:

Can the default scope be applied?

Band.default_scopable?

Returns:

  • (true | false)

    If the default scope can be applied.

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 95

def default_scopable?
  default_scoping? && !Threaded.without_default_scope?(self)
end

Instance Method Details

#check_scope_name(name) (private)

This method is for internal use only.

Warns or raises exception if overriding another scope or method.

Examples:

Warn or raise error if name exists.

Model.check_scope_name("test")

Parameters:

Raises:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 247

def check_scope_name(name)
  if _declared_scopes[name] || respond_to?(name, true)
    if Mongoid.scope_overwrite_exception
      raise Errors::ScopeOverwrite.new(self.name, name)
    else
      Mongoid.logger.warn(
        "Creating scope :#{name} which conflicts with #{self.name}.#{name}. " +
        "Calls to `Mongoid::Criteria##{name}` will delegate to " +
        "`Mongoid::Criteria##{name}` for criteria with klass #{self.name} " +
        "and will ignore the declared scope."
      )
    end
  end
end

#check_scope_validity(value) (private)

This method is for internal use only.

Checks if the intended scope is a valid object, either a criteria or proc with a criteria.

Examples:

Check if the scope is valid.

Model.check_scope_validity({})

Parameters:

  • value (Object)

    The intended scope.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 273

def check_scope_validity(value)
  unless value.respond_to?(:call)
    raise Errors::InvalidScope.new(self, value)
  end
end

#criteria

Alias for #with_default_scope.

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 198

alias :criteria :with_default_scope

#default_scope(value = nil) ⇒ Proc

Add a default scope to the model. This scope will be applied to all criteria unless #unscoped is specified.

Examples:

Define a default scope with a criteria.

class Band
  include Mongoid::Document
  field :active, type: Boolean
  default_scope where(active: true)
end

Define a default scope with a proc.

class Band
  include Mongoid::Document
  field :active, type: Boolean
  default_scope ->{ where(active: true) }
end

Parameters:

  • value (Proc | Criteria) (defaults to: nil)

    The default scope.

Returns:

  • (Proc)

    The default scope.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 83

def default_scope(value = nil)
  value = Proc.new { yield } if block_given?
  check_scope_validity(value)
  self.default_scoping = process_default_scope(value)
end

#define_scope_method(name) ⇒ Method (private)

This method is for internal use only.

Defines the actual class method that will execute the scope when called.

Examples:

Define the scope class method.

Model.define_scope_method(:active)

Parameters:

  • name (Symbol)

    The method/scope name.

Returns:

  • (Method)

    The defined method.

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 290

def define_scope_method(name)
  singleton_class.class_eval do
    define_method(name) do |*args, **kwargs|
      scoping = _declared_scopes[name]
      scope = instance_exec(*args, **kwargs, &scoping[:scope])
      extension = scoping[:extension]
      to_merge = scope || queryable

      criteria = if Mongoid.allow_scopes_to_unset_default_scope
                   to_merge
                 else
                   to_merge.empty_and_chainable? ? to_merge : with_default_scope.merge(to_merge)
                 end

      criteria.extend(extension)
      criteria
    end
  end
end

#process_default_scope(value) (private)

This method is for internal use only.

Process the default scope value. If one already exists, we merge the new one into the old one.

Examples:

Process the default scope.

Model.process_default_scope(value)

Parameters:

  • value (Criteria | Proc)

    The default scope value.

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 319

def process_default_scope(value)
  if existing = default_scoping
    ->{ existing.call.merge(value.to_proc.call) }
  else
    value.to_proc
  end
end

#queryableCriteria

This method is for internal use only.

Get a queryable, either the last one on the scope stack or a fresh one.

Examples:

Get a queryable.

Model.queryable

Returns:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 107

def queryable
  crit = Threaded.current_scope(self) || Criteria.new(self)
  crit.embedded = true if (crit.klass.embedded? && !crit.klass.cyclic?)
  crit
end

#scope(name, value, &block)

Create a scope that can be accessed from the class level or chained to criteria by the provided name.

Examples:

Create named scopes.

class Person
  include Mongoid::Document
  field :active, type: Boolean
  field :count, type: Integer

  scope :active, -> { where(active: true) }
  scope :at_least, ->(count){ where(:count.gt => count) }
end

Parameters:

  • name (Symbol)

    The name of the scope.

  • value (Proc)

    The conditions of the scope.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 132

def scope(name, value, &block)
  normalized = name.to_sym
  check_scope_validity(value)
  check_scope_name(normalized)
  _declared_scopes[normalized] = {
    scope: value,
    extension: Module.new(&block)
  }
  define_scope_method(normalized)
end

#scoped(options = nil) ⇒ Criteria

Note:

This will force the default scope to be applied.

Get a criteria for the document with normal scoping.

Examples:

Get the criteria.

Band.scoped(skip: 10)

Parameters:

  • options (Hash) (defaults to: nil)

    Query options for the criteria.

Options Hash (options):

  • :skip (Integer)

    Optional number of documents to skip.

  • :limit (Integer)

    Optional number of documents to limit.

  • :sort (Array)

    Optional sorting options.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 158

def scoped(options = nil)
  queryable.scoped(options)
end

#scopesHash

Returns a hash of all the scopes defined for this class, including scopes defined on ancestor classes.

Examples:

Get the defined scopes for a class

class Band
  include Mongoid::Document
  field :active, type: Boolean

  scope :active, -> { where(active: true) }
end
Band.scopes

Returns:

  • (Hash)

    The scopes defined for this class

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 51

def scopes
  defined_scopes = {}
  ancestors.reverse.each do |klass|
    if klass.respond_to?(:_declared_scopes)
      defined_scopes.merge!(klass._declared_scopes)
    end
  end
  defined_scopes.freeze
end

#unscopedCriteria | Object

Note:

This will force the default scope, as well as any scope applied using “.with_scope“, to be removed.

Get the criteria without any scoping applied.

Examples:

Get the unscoped criteria.

Band.unscoped

Yield to block with no scoping.

Band.unscoped do
  Band.where(name: "Depeche Mode")
end

Returns:

  • (Criteria | Object)

    The unscoped criteria or result of the block.

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 177

def unscoped
  if block_given?
    without_default_scope do
      with_scope(nil) do
        yield(self)
      end
    end
  else
    queryable.unscoped
  end
end

#with_default_scopeCriteria Also known as: #criteria

Get a criteria with the default scope applied, if possible.

Examples:

Get a criteria with the default scope.

Model.with_default_scope

Returns:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 195

def with_default_scope
  queryable.with_default_scope
end

#with_scope(criteria) ⇒ Criteria

Pushes the provided criteria onto the scope stack, and removes it after the provided block is yielded.

Examples:

Yield to the criteria.

Person.with_scope(criteria)

Parameters:

  • criteria (Criteria)

    The criteria to apply.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 209

def with_scope(criteria)
  previous = Threaded.current_scope(self)
  Threaded.set_current_scope(criteria, self)
  begin
    yield criteria
  ensure
    Threaded.set_current_scope(previous, self)
  end
end

#without_default_scopeObject

Execute the block without applying the default scope.

Examples:

Execute without the default scope.

Band.without_default_scope do
  Band.where(name: "Depeche Mode")
end

Returns:

  • (Object)

    The result of the block.

[ GitHub ]

  
# File 'lib/mongoid/scopable.rb', line 227

def without_default_scope
  Threaded.begin_without_default_scope(self)
  yield
ensure
  Threaded.exit_without_default_scope(self)
end