Overview
En esta guía, aprenderá a implementar ámbitos en sus modelos Mongoid. Los ámbitos ofrecen una forma práctica de reutilizar criterios de filtro comunes. Para obtener más información sobre la creación de criterios de filtro, consulte Especifique una guía de consulta de documentos.
Puede implementar alcances en su aplicación para reducir el código repetido si está aplicando los mismos criterios a la mayoría de las consultas.
Ámbitos con nombre
Los ámbitos con nombre son criterios definidos al cargar la clase y referenciados por un nombre proporcionado. Al igual que los criterios de filtro, se cargan de forma diferida y son encadenables.
Este ejemplo define una Band modelo que incluye los siguientes ámbitos con nombre:
japanese: Coincide con 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 alcance based_in, que coincide con los documentos en los que el valor del campo country es el valor especificado que se pasa 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 realizar consultas utilizando el ámbito based_in, como se muestra en el siguiente código:
Band.based_in("Spain")
Mongoid le permite definir un ámbito que ensombrece 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
Puede indicarle a Mongoid que genere un error cuando un ámbito sobrescribe un método de clase existente estableciendo 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 de configuración de la aplicación.
Ámbitos predeterminados
Los ámbitos predeterminados son útiles cuando se aplican los mismos criterios a la mayoría de las consultas. Al definir un ámbito predeterminado, se especifican estos criterios como predeterminados para cualquier consulta que utilice el modelo. Los ámbitos predeterminados devuelven Criteria objetos.
Para crear un ámbito predeterminado, debe definir el método default_scope en su clase de 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 predeterminado en una definición de campo y en el ámbito predeterminado, el valor en el ámbito predeterminado tendrá 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 define un ámbito predeterminado que hace referencia al campo tour.year, se inicializa un nuevo modelo con el campo tour.year en lugar de un campo tour con un objeto anidado que contiene un campo year.
Al realizar consultas, Mongoid interpreta correctamente la notación de puntos y coincide con los 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
Supongamos que crea un modelo Label que contiene una asociación con un Band cuyo valor de active es true. Al actualizar el campo active a false, Mongoid lo carga a pesar del alcance predeterminado. Para ver los documentos de 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 ámbito predeterminado de la misma manera que cualquier otra condición de consulta. Esto puede generar un comportamiento inesperado al usar los métodos or y nor.
Los siguientes ejemplos demuestran cómo Mongoid interpreta las consultas en modelos con un alcance predeterminado:
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 consulta.
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
Puede utilizar el método with_scope para cambiar el alcance predeterminado en un bloque en tiempo de ejecución.
El siguiente modelo define el ámbito mexican denominado:
class Band include Mongoid::Document field :country, type: String field :genres, type: Array scope :mexican, ->{ where(country: "Mexico") } end
Puede utilizar el método with_scope para establecer el ámbito nombrado mexican como el ámbito predeterminado 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 devuelven objetos Criteria como ámbitos. Puedes realizar consultas usando 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 obtener más información sobre cómo personalizar sus modelos Mongoid, consulte las guías Modele sus datos.