Overview
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.
Ámbitos con nombre
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 campocountryes"Japan"rock: Coincide con documentos en los que el valor del campogenreincluye"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
Alcance avanzado
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.
Ámbitos por defecto
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.
Inicialización de campo
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.
Asociaciones
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
Comportamiento de consulta or y nor
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.
Deshabilitar ámbito al consultar
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
Anular el alcance predeterminado en tiempo de ejecución
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
Métodos de clase
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
Información Adicional
Para aprender más sobre cómo personalizar tus modelos de Mongoid, consulta las guías Modela tus datos.