Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Alcance

En esta guía, puedes aprender cómo implementar alcances en tus modelos de Mongoid. Los ámbitos proporcionan una manera conveniente de reutilizar criterios de filtro comunes. Para obtener más información sobre la creación de criterios de filtro, consulte la Especifica una query de documento guía.

Podrías implementar ámbitos en tu aplicación para reducir la repetición de código si aplicas los mismos criterios para la mayoría de las queries.

Los alcances nombrados son criterios definidos en la carga de la clase que se referencian por un nombre proporcionado. Similar a los criterios de filtro, se cargan de forma perezosa y son encadenables.

Este ejemplo define una Band modelo que incluye los siguientes ámbitos nombrados:

  • japanese:: Coincide con los documentos en los que el valor del campo country es "Japan"

  • rock: Coincide con documentos en los que el valor del campo genre incluye "rock"

class Band
include Mongoid::Document
field :country, type: String
field :genres, type: Array
scope :japanese, ->{ where(country: "Japan") }
scope :rock, ->{ where(:genres.in => [ "rock" ]) }
end

Luego, puedes hacer queries utilizando los ámbitos nombrados. La siguiente query utiliza los ámbitos nombrados para coincidir con documentos en los que el valor del campo country es "Japan" y el valor del campo genre incluye "rock":

Band.japanese.rock

Puede definir Proc objetos y bloques en ámbitos con nombre para que acepten parámetros y amplíen la funcionalidad.

Este ejemplo define un modelo Band que incluye el ámbito based_in, que hace coincidir los documentos en los que el valor del campo country es el valor especificado pasado como parámetro:

class Band
include Mongoid::Document
field :name, type: String
field :country, type: String
scope :based_in, ->(country){ where(country: country) }
end

Luego puedes query utilizando el alcance based_in, como se muestra en el siguiente código:

Band.based_in("Spain")

Mongoid te permite definir un ámbito que oscurece un método de clase existente, como se muestra en el siguiente ejemplo:

class Band
include Mongoid::Document
def self.on_tour
true
end
scope :on_tour, ->{ where(on_tour: true) }
end

Se puede indicar a Mongoid que genere un error cuando un ámbito sobrescriba un método de clase existente configurando la opción de configuración scope_overwrite_exception en true.

Para obtener más información sobre esta configuración, consulte la guía Conectarse a MongoDB.

Los ámbitos por defecto son útiles para casos en los que se aplican los mismos criterios a la mayoría de las queries. Al definir un alcance por defecto, especificas estos criterios como el valor por defecto para cualquier query que utilice el modelo. Los ámbitos por defecto devuelven Criteria objetos.

Para crear un alcance por defecto, debes definir el método default_scope en tu clase modelo.

El siguiente código define el método default_scope en el modelo Band para recuperar únicamente documentos en los que el valor del campo active sea true:

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

Luego, cualquier consulta en el modelo Band prefiltra los documentos en los que el valor active es true.

Al especificar un alcance predeterminado, se inicializan los campos de los nuevos modelos con los valores dados en el alcance predeterminado si esos valores son literales, como valores booleanos o números enteros.

Nota

Conflictos de campo y alcance

Si proporciona un valor por defecto en la definición de un campo y en el ámbito por defecto, el valor en el ámbito por defecto tiene prioridad, como se muestra en el siguiente ejemplo:

class Band
include Mongoid::Document
field :name, type: String
field :on_tour, type: Boolean, default: true
default_scope ->{ where(on_tour: false) }
end
# Creates a new Band instance in which "on_tour" is "false"
Band.new

No se recomienda utilizar notación de puntos para hacer referencia a campos anidados en ámbitos predeterminados. Esto puede hacer que Mongoid inicialice campos inesperados en nuevos modelos.

Por ejemplo, si se define un alcance por defecto que hace referencia al campo tour.year, un modelo nuevo se inicializa con el campo tour.year en lugar de un campo tour con un objeto anidado que contiene un campo year.

Cuando se consulta, Mongoid interpreta correctamente la notación de puntos y hace coincidir documentos en los que un campo anidado tiene el valor especificado.

Si define un ámbito predeterminado en un modelo que forma parte de una asociación, debe recargar la asociación para que se aplique el ámbito. Esto es necesario cuando se modifica un valor de un documento en la asociación que afecta su visibilidad al aplicar el ámbito.

Este ejemplo utiliza los siguientes modelos:

class Label
include Mongoid::Document
field :name, type: String
embeds_many :bands
end
class Band
include Mongoid::Document
field :name, type: String
field :active, default: true
embedded_in :label
default_scope ->{ where(active: true) }
end

Suponga que crea un modelo Label que contiene una asociación a un Band en el que el valor de active es true. Cuando se actualiza el campo active a false, Mongoid sigue cargándolo a pesar del ámbito por defecto. Para ver los documentos en la asociación con el alcance aplicado, debe llamar al operador reload.

El siguiente código demuestra esta secuencia:

label = Label.new(name: "Hello World Records")
band = Band.new(name: "Ghost Mountain")
label.bands.push(band)
label.bands # Displays the Band because "active" is "true"
band.update_attribute(:active, false) # Updates "active" to "false"
# Displays the "Ghost Mountain" band
label.bands # => {"_id":"...","name":"Ghost Mountain",...}
# Won't display "Ghost Mountain" band after reloading
label.reload.bands # => nil

Mongoid trata los criterios en un alcance predeterminado de la misma manera que cualquier otra condición de query. Esto puede llevar a un comportamiento sorprendente al usar los métodos or y nor.

Los siguientes ejemplos demuestran cómo Mongoid interpreta las queries en modelos con un alcance por defecto:

class Band
include Mongoid::Document
field :name
field :touring
field :member_count
default_scope ->{ where(touring: true) }
end
# Combines the condition to the default scope with "and"
Band.where(name: 'Infected Mushroom')
# Interpreted query:
# {"touring"=>true, "name"=>"Infected Mushroom"}
# Combines the first condition to the default scope with "and"
Band.where(name: 'Infected Mushroom').or(member_count: 3)
# Interpreted query:
# {"$or"=>[{"touring"=>true, "name"=>"Infected Mushroom"}, {"member_count"=>3}]}
# Combines the condition to the default scope with "or"
Band.or(member_count: 3)
# Interpreted query:
# {"$or"=>[{"touring"=>true}, {"member_count"=>3}]}

Para obtener más información sobre las operaciones lógicas, consulte Operaciones lógicas en la guía Especificar una query.

Puede indicarle a Mongoid que no aplique el alcance predeterminado utilizando el operador unscoped, como se muestra en los siguientes ejemplos:

# Inline example
Band.unscoped.where(name: "Depeche Mode")
# Block example
Band.unscoped do
Band.where(name: "Depeche Mode")
end

Puedes utilizar el método with_scope para cambiar el ámbito por defecto en un bloque en tiempo de ejecución.

El siguiente modelo define el alcance nombrado mexican:

class Band
include Mongoid::Document
field :country, type: String
field :genres, type: Array
scope :mexican, ->{ where(country: "Mexico") }
end

Puedes usar el método with_scope para establecer el ámbito nombrado mexican como el ámbito por defecto en tiempo de ejecución, como se muestra en el siguiente código:

Band.with_scope(Band.mexican) do
Band.all
end

Mongoid trata los métodos de clase que retornan Criteria objetos como alcances. Se puede realizar consultas utilizando estos métodos de clase, como se muestra en el siguiente ejemplo:

class Band
include Mongoid::Document
field :name, type: String
field :touring, type: Boolean, default: true
def self.touring
where(touring: true)
end
end
Band.touring

Para aprender más sobre cómo personalizar tus modelos de Mongoid, consulta las guías Modela tus datos.

Volver

Especifica un query

En esta página