Overview
Las asociaciones en Mongoid permiten crear relaciones entre modelos. En esta guía, aprenderá sobre los diferentes tipos de asociaciones que Mongoid admite y cómo usarlas en su aplicación.
Asociaciones referenciadas
Las asociaciones referenciadas le permiten crear una relación entre dos modelos donde uno hace referencia a otro. Mongoid soporta los siguientes tipos de asociación referenciada:
has_onehas_manybelongs_tohas_and_belongs_to_many
Las siguientes secciones describen cómo utilizar cada uno de estos tipos de asociación.
Tiene uno
Puede utilizar la macro has_one para declarar que los documentos representados por una clase también contienen un documento representado por una clase hija independiente. El siguiente ejemplo crea una clase Band con una relación has_one a una clase Studio:
class Band include Mongoid::Document has_one :studio end
Cuando declaras una asociación has_one, la clase hijo también debe usar la asociación belongs_to que referencia a la clase padre. El siguiente ejemplo muestra la clase Studio referenciada en la clase anterior Band:
class Studio include Mongoid::Document belongs_to :band end
Para obtener más información sobre la macro belongs_to, consulta la Pertenece a la sección.
Puede usar validaciones para asegurarse de que la clase secundaria esté presente en su clase principal, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document has_one :studio validates_presence_of :studio end
Para obtener más información sobre las validaciones en Mongoid, consulte el Validations guide.
Tiene muchos
Puedes usar la macro has_many para declarar que los documentos representados por una clase contienen múltiples documentos secundarios representados por otra clase. El siguiente ejemplo crea una clase Band con una relación has_many a una clase Members:
class Band include Mongoid::Document has_many :members end
Cuando declaras una asociación has_many, la clase hijo también debe usar la asociación belongs_to que referencia a la clase padre. El siguiente ejemplo muestra la clase Member referenciada en la clase anterior Band:
class Member include Mongoid::Document belongs_to :band end
Para obtener más información sobre la macro belongs_to, consulta la sección Pertenece a.
Puede usar validaciones para asegurarse de que la clase secundaria esté presente en su clase principal, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document has_many :members validates_presence_of :members end
Para obtener más información sobre las validaciones en Mongoid, consulte la guía de Validaciones.
Recuperar información de la asociación
Puedes utilizar el método any? en una asociación has_many para determinar si la asociación contiene algún documento sin recuperar el conjunto completo de documentos de la base de datos.
El siguiente ejemplo utiliza el método any? para determinar si los documentos de la clase Band contienen algún documento Members:
band = Band.first band.members.any?
También puedes utilizar el método any? con un filtro para encontrar documentos que cumplan con un criterio determinado, como se muestra en el siguiente ejemplo:
band = Band.first band.members.any? { |member| member.instrument == 'piano' }
Puedes proporcionar un nombre de clase al método any? para filtrar los resultados por el nombre de la clase. Esto es útil para asociaciones polimórficas:
class Drummer < Member end band = Band.first band.members.any?(Drummer)
Nota
Una vez que los datos de la clase asociada se cargan a Mongoid, las siguientes llamadas al método any? no query la base de datos. En su lugar, Mongoid utiliza los datos que ya están cargados en la memoria.
También puede llamar al método exists? para determinar si hay algún documento persistente en la asociación. El método exists? siempre consulta la base de datos y solo verifica los documentos que han sido guardados en la base de datos. El método exists? no permite filtrar ni acepta ningún argumento.
El siguiente ejemplo usa el método exists? para determinar si existen documentos Members persistidos en la clase Band:
band = Band.create! # Member is not persisted. band.members.build band.members.exists? # Outputs: false # Persist the member band.members.map(&:save!) band.members.exists? # Outputs: true
Pertenece a
Utiliza la macro belongs_to para declarar que un documento representado por una clase es hijo de un documento representado por otra clase. Por defecto, el campo _id de la clase principal se almacena en la clase secundaria. El siguiente ejemplo crea una clase Members con una asociación belongs_to a una clase Band:
class Members include Mongoid::Document belongs_to :band end
Puedes permitir que Mongoid persista documentos en la base de datos sin almacenar el _id de la clase padre asociada estableciendo la opción optional en true, como se muestra en el siguiente ejemplo:
class Members include Mongoid::Document belongs_to :band, optional: true end
Tip
Puede cambiar globalmente el comportamiento predeterminado de la asociación belongs_to para no requerir su clase principal estableciendo la opción de configuración belongs_to_required_by_default en false en la configuración de su aplicación.
Puedes especificar una asociación de belongs_to en una clase secundaria sin especificar una asociación de has_one ni de has_many en la clase principal. Al hacerlo así, no se puede acceder a los campos del documento secundario desde la clase principal, pero sí se puede acceder a los campos principales que se almacenan en la clase secundaria, como el campo _id del principal. En el siguiente ejemplo, la clase Band no puede acceder a la clase Members, pero la clase Members sí puede acceder a la clase Band:
class Band include Mongoid::Document end class Members include Mongoid::Document belongs_to :band end
Para mayor claridad, de manera opcional, puedes establecer la opción inverse_of en nil para indicar que la clase padre no contiene una asociación has_one o has_many con la clase hija, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document end class Members include Mongoid::Document belongs_to :band, inverse_of: nil end
Tiene y Pertenece a Muchos
Utilice el macro has_and_belongs_to_many para declarar que un modelo de clase contiene una relación de muchos a muchos con otra clase. En una relación de muchos a muchos, cada documento de una clase se puede asociar con varios documentos en otra clase. El siguiente ejemplo crea una clase Band con una relación has_and_belongs_to_many a una clase Members. Un documento Band puede hacer referencia a varios documentos Members, y un documento Members puede hacer referencia a varios documentos Band.
class Band include Mongoid::Document has_and_belongs_to_many :members end class Members include Mongoid::Document has_and_belongs_to_many :bands end
Cuando declaras una asociación has_and_belongs_to_many, ambas instancias del modelo almacenan una lista de los valores _id del documento asociado. Puedes establecer la opción inverse_of en nil para almacenar los valores _id del documento asociado solo en una de las instancias del modelo. El siguiente ejemplo solicita a Mongoid que almacene los valores _id del documento asociado solo en la clase Band:
class Band include Mongoid::Document has_and_belongs_to_many :tags, inverse_of: nil end class Tag include Mongoid::Document end
Tip
Cuando actualizas un documento que tiene una asociación has_and_belongs_to_many, Mongoid establece el campo updated_at del documento actualizado, pero no establece el campo updated_at de los documentos asociados.
Asociaciones referenciadas por consulta
Puede utilizar un pipeline de agregación para hacer query documentos en asociaciones referenciadas. El pipeline de agregación te permite crear consultas en varias colecciones y manipular los datos en un formato específico. Para obtener más información sobre el uso del pipeline de agregación, consulta la guía de Agregación.
Para consultas sencillas, puede consultar la asociación directamente. Al consultar directamente una colección, solo puede consultar los campos y valores que se encuentran en ella. No puede consultar directamente las colecciones asociadas a la que está consultando.
Por ejemplo, consideremos las siguientes clases Band y Tour:
class Band include Mongoid::Document has_many :tours field :name, type: String end class Tour include Mongoid::Document belongs_to :band field :year, type: Integer end
El siguiente ejemplo query la clase Tour para los documentos que tienen un valor de year de 2000 o superior y guarda el band_id de esos documentos. Luego query la clase Band para obtener documentos que tienen esos valores de band_id.
band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id) bands = Band.find(band_ids)
Asociaciones incrustadas
Puede usar asociaciones integradas para almacenar diferentes tipos de documentos en la misma colección. Mongoid admite asociaciones integradas con las siguientes macros:
embeds_oneembeds_manyembedded_inrecursively_embeds_onerecursively_embeds_many
Las siguientes secciones describen cómo emplear estos tipos de asociación.
Embeds One
Para especificar que un modelo de clase contiene un documento incrustado de un tipo de clase diferente, utilice la macro embeds_one en la clase padre y la macro embedded_in en la clase incrustada. El siguiente ejemplo crea una clase Band con una clase Label incrustada:
class Band include Mongoid::Document embeds_one :label end class Label include Mongoid::Document field :name, type: String embedded_in :band end
Mongoid almacena los documentos incrustados con la macro embeds_one en el documento principal como un campo con el mismo nombre que la clase incrustada. Los Label documentos anteriores están almacenados en el documento Band, como se muestra en el siguiente ejemplo:
# Band document { "_id" : ObjectId("..."), "label" : { "_id" : ObjectId("..."), "name" : "Periphery", } }
Puede almacenar el documento incrustado con un nombre diferente utilizando la opción store_as, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document embeds_one :label, store_as: "record_label" end
Incrusta muchos
Para especificar que un modelo de clase contiene varios documentos incrustados de un tipo de clase diferente, utilice la macro embeds_many en la clase principal y la macro embedded_in en la clase incrustada. El siguiente ejemplo crea una clase Band con varios documentos incrustados de tipo Album:
class Band include Mongoid::Document embeds_many :albums end class Album include Mongoid::Document field :name, type: String embedded_in :band end
Mongoid almacena los documentos embebidos con la macro embeds_many en el documento principal como un campo de arreglo con el mismo nombre que la clase embebida. Los documentos Album anteriores se almacenan en el documento Band, como se muestra en el siguiente ejemplo:
{ "_id" : ObjectId("..."), "albums" : [ { "_id" : ObjectId("..."), "name" : "Omega", } ] }
Puede almacenar el documento incrustado con un nombre diferente utilizando la opción store_as, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document embeds_many :albums, store_as: "records" end
Embedding recursivo
Puedes insertar uno o más documentos del mismo tipo en una clase principal utilizando las macros recursively_embeds_one y recursively_embeds_many. Ambas macros proporcionan acccesores para los documentos principal e hijo a través de un método parent_* y un método child_*, donde * representa el nombre de la clase. El siguiente ejemplo crea una clase Band que inserta recursivamente múltiples otros documentos Band para representar múltiples nombres de bandas:
class Band include Mongoid::Document field :name, type: String recursively_embeds_many end
Puedes acceder a los documentos padre e hijo mediante los métodos parent_band y child_band, como se muestra en el siguiente ejemplo:
root = Band.new(name: "Linkin Park") # Add child bands child_one = root.child_band.build(name: "Lincoln Park") child_two = root.child_band.build(name: "Xero") # Access parent band child_one.parent_band # Outputs: root
Query de asociaciones integradas
Se pueden acceder a los documentos incrustados al consultar la colección de la clase superior utilizando la notación de puntos.
El siguiente ejemplo utiliza notación de puntos para query documentos tipo Tour incrustados en una clase Band. El query devuelve documentos que tienen un valor de tours.year de 2000 o superior:
Band.where('tours.year' => {'$gte' => 2000})
Puede utilizar el método de proyección pluck para recuperar documentos incrustados sin recuperar sus documentos parentales asociados, como se muestra en el siguiente ejemplo:
# Get awards for bands that have toured since 2000 Band.where('tours.year' => {'$gte' => 2000}).pluck(:awards)
Puedes usar los métodos de query de Mongoid para realizar coincidencias incrustadas. Esto te permite consultar asociaciones incrustadas de documentos que ya han sido cargados en la aplicación. Mongoid implementa la coincidencia embebida sin enviar consultas al servidor.
Los siguientes operadores del query son compatibles con la coincidencia incrustada:
El siguiente ejemplo query el campo tours incrustado de un documento Band cargado utilizando el operador de comparación $gte:
band = Band.where(name: 'Astral Projection').first tours = band.tours.where(year: {'$gte' => 2000})
La coincidencia integrada en documentos cargados tiene las siguientes limitaciones conocidas:
La coincidencia incrustada no está implementada para las siguientes funcionalidades:
Operadores que ejecutan código JavaScript, como $where
Operadores que se implementan a través de otras funcionalidades del servidor, como $expr y $jsonSchema
Mongoid expande los argumentos
Rangea hashes con condiciones$gtey$lte. Esto puede generar consultas no válidas en algunos casos y generar una excepciónInvalidQuery.Con el operador
$regex, no puedes especificar un objeto de expresión regular como patrón a la vez que proporcionas opciones en el campo$options. Solo puedes proporcionar opciones si el patrón de expresión regular es un string.
Omitir campos _id
Por defecto, Mongoid añade un campo _id a los documentos incrustados. Se puede omitir este campo de los documentos incrustados mediante la especificación explícita del campo _id en el modelo y la omisión del valor por defecto. El siguiente ejemplo ordena a Mongoid no agregar un campo _id a la clase Albums:
class Album include Mongoid::Document field :name, type: String field :_id, type: Object embedded_in :band end
En la clase Albums anterior, el campo _id no se agrega automáticamente. Sin un valor por defecto, Mongoid no almacena el valor en la base de datos a menos que proporciones uno en tu modelo.
Borrar asociaciones incrustadas
Puede eliminar documentos secundarios de las asociaciones embeds_many mediante uno de los siguientes métodos:
cleardelete_alldestroy_all
El clear método utiliza el operador $unset para eliminar una asociación incrustada completa del documento principal. El clear método no ejecuta ninguna destroy devolución de llamada. El siguiente ejemplo utiliza el clear método para eliminar todas las asociaciones incrustadas de la Band clase:
band = Band.find(...) band.tours.clear
El método delete_all utiliza el operador $pullAll para remover documentos en una asociación embebida. delete_all carga la asociación si aún no se ha cargado, y entonces solo remueve los documentos que existen en la aplicación. El método delete_all no ejecuta ninguna función de retorno de destroy. El siguiente ejemplo utiliza el método delete_all para remover todos los documentos Album integrados de la clase Band:
band = Band.find(...) band.tours.delete_all
El método destroy_all también utiliza el operador operador $pullAll para eliminar documentos en una asociación embebida. También ejecuta cualquier destroy función de retorno que se haya definido en los documentos asociados. El siguiente ejemplo utiliza el método destroy_all para remover todos los documentos Album embebidos de la clase Band:
band = Band.find(...) band.tours.destroy_all
Personalizar el comportamiento de la asociación
Puedes usar Mongoid para personalizar cómo se comportan las asociaciones en tu aplicación. Las siguientes secciones describen formas de personalizar los comportamientos de asociación.
Extensiones
Las extensiones permiten añadir funcionalidades personalizadas a una asociación. Se puede definir una extensión en una asociación especificando un bloque en la definición de la asociación, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document embeds_many :albums do def find_by_name(name) where(name: name).first end end end band.albums.find_by_name("Omega") # returns album "Omega"
Nombres de asociaciones personalizadas
Puedes usar la macro class_name para especificar un nombre de clase personalizado para una asociación. Esto es útil cuando desea asignar a la asociación un nombre distinto al de la clase. El siguiente ejemplo utiliza la macro class_name para especificar que una asociación embebida llamada records representa la clase Album:
class Band include Mongoid::Document embeds_many :records, class_name: "Album" end
Teclas personalizadas
Por defecto, Mongoid utiliza el campo _id de la clase principal al buscar asociaciones. Puedes especificar diferentes campos para usar mediante el uso de las macros primary_key y foreign_key. El siguiente ejemplo especifica una nueva clave primaria y una clave foránea para la asociación albums en una clase Band:
class Band include Mongoid::Document field :band_id, type: String has_many :albums, primary_key: 'band_id', foreign_key: 'band_id_ref' end class Album include Mongoid::Document field :band_id_ref, type: String belongs_to :band, primary_key: 'band_id', foreign_key: 'band_id_ref' end
Si especifica una asociación has_and_belongs_to_many, también puede usar las macros inverse_primary_key y inverse_foreign_key. La macro inverse_primary_key especifica el campo del modelo local que el modelo remoto utiliza para buscar los documentos. La macro inverse_foreign_key especifica el campo del modelo remoto que almacena los valores encontrados en inverse_primary_key.
El siguiente ejemplo especifica una nueva clave primaria y foránea para las clases Band y Members en una asociación has_and_belongs_to_many:
class Band include Mongoid::Document field :band_id, type: String field :member_ids, type: Array has_many :members, primary_key: 'member_id', foreign_key: 'member_ids', inverse_primary_key: 'band_id', inverse_foreign_key: 'band_ids' end class Member include Mongoid::Document field :member_id, type: String field :band_ids, type: Array has_many :bands, primary_key: 'band_id', foreign_key: 'band_ids', inverse_primary_key: 'member_id', inverse_foreign_key: 'member_ids' end
Alcances personalizados
Puede especificar el alcance de una asociación usando el parámetro scope. El parámetro scope determina los documentos que Mongoid considera parte de una asociación. Una asociación con alcance devuelve solo los documentos que cumplen las condiciones de alcance cuando se consultan. Puede establecer el scope en un Proc con una aridad de cero o en un Symbol que haga referencia a un alcance nombrado en el modelo asociado. El siguiente ejemplo establece ámbitos personalizados en las asociaciones de una clase Band:
class Band include Mongoid::Document has_many :albums, scope: -> { where(published: true) } # Uses a scope called "upcoming" on the Tour model has_many :tours, scope: :upcoming end
Nota
Puedes añadir documentos que no cumplen con las condiciones del alcance a una asociación. Mongoid guarda los documentos en la base de datos y estos aparecerán en la memoria asociada. Sin embargo, no verás los documentos al consultar la asociación.
validación
Cuando Mongoid carga una asociación en la memoria, por defecto, utiliza la macro validates_associated para validar que también estén presentes todos los hijos. Mongoid valida a los hijos para los siguientes tipos de asociaciones:
embeds_manyembeds_onehas_manyhas_onehas_and_belongs_to_many
Puede desactivar este comportamiento de validación configurando la macro validate en false al definir la asociación, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document embeds_many :albums, validate: false end
polimorfismo
Mongoid admite el polimorfismo en las clases hijas de asociaciones uno a uno y uno a muchos. Las asociaciones polimórficas permiten que una sola asociación contenga objetos de diferentes tipos de clases. Se puede definir una asociación polimórfica configurando la opción polymorphic como true en una asociación hija y añadiendo la opción as a la asociación principal. El siguiente ejemplo crea una asociación polimórfica en una clase Band:
class Tour include Mongoid::Document has_one :band, as: :featured end class Label include Mongoid::Document has_one :band, as: :featured end class Band include Mongoid::Document belongs_to :featured, polymorphic: true end
En el ejemplo anterior, la asociación de :featured en la clase Band puede contener un documento Label o Album.
Importante
Mongoid solo admite el polimorfismo de hijo a padre. No se puede especificar una asociación superior de has_one o has_many como polimórfica.
has_and_belongs_to_many Las asociaciones no admiten polimorfismo.
Tipos polimórficos personalizados
A partir de la versión 9.0.2, Mongoid admite tipos polimórficos personalizados mediante un registro global. Puede especificar claves alternativas para representar diferentes clases, desvinculando así su código de los datos. El siguiente ejemplo especifica la cadena "artist" como clave alternativa para la clase Band:
class Band include Mongoid::Document identify_as 'artist' has_many :albums, as: :record end
En el ejemplo anterior, la directiva identify_as indica a Mongoid que almacene la clase Band en la base de datos como la cadena "artist".
También puede especificar varios alias, como se muestra en el siguiente ejemplo:
class Band include Mongoid::Document identify_as 'artist', 'group', 'troupe' has_many :albums, as: :record end
En el ejemplo anterior, artist es el nombre por defecto y los demás se usan únicamente para buscar registros. Esto le permite refactorizar su código sin romper las asociaciones en sus datos.
Los alias de tipo polimórfico son globales. Las claves que se especifiquen deben ser únicas en toda la base de código. Sin embargo, puede registrar resolutores alternativos que se puedan usar para diferentes subconjuntos de sus modelos. En este caso, las claves deben ser únicas solo para cada resolutor. El siguiente ejemplo muestra cómo registrar resolutores alternativos:
Mongoid::ModelResolver.register_resolver Mongoid::ModelResolver.new, :mus Mongoid::ModelResolver.register_resolver Mongoid::ModelResolver.new, :tool module Music class Band include Mongoid::Document identify_as 'bnd', resolver: :mus end end module Tools class Band include Mongoid::Document identify_as 'bnd', resolver: :tool end end
Tanto Music::Band como Tools::Band están enmascarados como "bnd", pero cada modelo utiliza su propio resolver para evitar conflictos.
Comportamiento dependiente
Puede proporcionar opciones dependent a las asociaciones referenciadas para especificar cómo Mongoid gestiona los documentos asociados al eliminar un documento. Puede especificar las siguientes opciones:
delete_all:Elimina todos los documentos secundarios sin ejecutar ninguna devolución de llamada de modelo.destroy:Elimina los documentos secundarios y ejecuta todas las devoluciones de llamadas del modelo.nullify: Establece la clave externa de los documentos secundarios ennil. El documento secundario podría quedar huérfano si solo el documento principal hace referencia a él.restrict_with_exceptionAumenta una excepción si el documento secundario no está vacío.restrict_with_error: Cancela la operación y retornafalsesi el documento hijo no está vacío.
Si no se especifican opciones dependent, Mongoid deja el documento secundario sin cambios cuando se elimina el documento principal. El documento secundario sigue haciendo referencia al documento principal eliminado, y si solo se hace referencia a través del principal, el documento secundario queda huérfano.
El siguiente ejemplo especifica dependent opciones en la clase Band:
class Band include Mongoid::Document has_many :albums, dependent: :delete_all belongs_to :label, dependent: :nullify end
Guardado automático de asociaciones referenciadas
Por defecto, Mongoid no guarda automáticamente documentos asociados de asociaciones no embebidas al guardar el documento padre. Esto puede resultar en referencias colgantes a documentos que no existen.
Puede usar la opción autosave en una asociación referenciada para guardar automáticamente los documentos asociados al guardar el documento principal. El siguiente ejemplo crea una clase Band con una clase Album asociada y especifica la opción autosave:
class Band include Mongoid::Document has_many :albums end class Album include Mongoid::Document belongs_to :band, autosave: true end band = Band.new album = Album.create!(band: band) # The band is persisted at this point.
Nota
Mongoid añade automáticamente la funcionalidad de guardado automático a una asociación que usa la opción accepts_nested_attributes_for.
No se necesita especificar la opción autosave para asociaciones incrustadas porque Mongoid guarda los documentos incrustados en el documento principal.
Autoconstrucción
Puedes agregar la opción autobuild a las asociaciones uno a uno, como has_one y embeds_one, para instanciar automáticamente un nuevo documento al acceder a una asociación nil. El siguiente ejemplo añade la opción autobuild a una asociación en la clase Band:
class Band include Mongoid::Document embeds_one :label, autobuild: true has_one :producer, autobuild: true end
Contacto
Cuando Mongoid toca un documento, actualiza el campo updated_at del documento a la fecha y hora actual. Puedes añadir la opción touch a cualquier belongs_to asociación para asegurar que Mongoid toque el documento padre cada vez que se actualice el documento hijo. El siguiente ejemplo añade la opción touch a una asociación en la clase Band:
class Band include Mongoid::Document field :name belongs_to :label, touch: true end
También puedes utilizar la opción touch para especificar otro campo en la asociación principal, como una string o un símbolo. Cuando Mongoid toca la asociación principal, establece tanto el campo updated_at como el campo especificado en la fecha y hora actuales.
El siguiente ejemplo instruye a Mongoid que toque el campo bands_updated_at:
class Band include Mongoid::Document belongs_to :label, touch: :bands_updated_at end
Nota
En asociaciones embebidas, cuando se toca un documento incrustado, Mongoid toca a sus padres recursivamente. Por lo tanto, no es necesario agregar un atributo touch a una asociación embedded_in.
Mongoid no admite especificar campos adicionales para actualizar en embedded_in asociaciones.
Caché de contador
Utilice la opción counter_cache para almacenar el número de objetos que pertenecen a un campo asociado. Al especificar esta opción, Mongoid almacena un campo de contador en el modelo principal asociado.
La opción counter_cache acepta uno de los dos valores siguientes para el nombre del campo de contador:
trueMongoid utiliza el nombre de campo de contador por defecto, en función del nombre de la relación. Por ejemplo, si la asociación se llamaBand, el nombre del campo de contador por defecto esbands_count.Un
stringosymbol: Mongoid usa ese valor directamente como el nombre del campo del contador.
Se puede proporcionar el contenedor para la caché del contador de una de las siguientes maneras:
Defina un campo explícito de contador en el modelo principal.
Incluya el módulo
Mongoid::Attributes::Dynamicen el modelo principal, lo que permite a Mongoid crear el campo de contador dinámicamente en el primer uso.
Campo de contador explícito
En este enfoque, declara el campo contador directamente en el modelo principal. Esto es útil cuando se quiere un esquema fijo y tipos de campos explícitos.
El siguiente ejemplo declara un campo bands_count explícito en la clase Label y utiliza el nombre de campo de contador por defecto:
class Band include Mongoid::Document # Uses the default counter field name: bands_count belongs_to :label, counter_cache: true end class Label include Mongoid::Document field :bands_count, type: Integer has_many :bands end
También puedes especificar un nombre de campo de contador personalizado pasando una string a la opción counter_cache:
class Band include Mongoid::Document belongs_to :label, counter_cache: :active_bands_count end class Label include Mongoid::Document field :active_bands_count, type: Integer has_many :bands end
Campo de Contador Dinámico
Si incluyes el módulo Mongoid::Attributes::Dynamic en el modelo padre, Mongoid puede crear y actualizar el campo de contador dinámicamente durante la ejecución. Esto es útil cuando quieres un esquema flexible y no quieres declarar explícitamente el campo del contador.
El siguiente ejemplo utiliza Mongoid::Attributes::Dynamic para permitir que Mongoid cree el campo de contador dinámicamente en la clase Label:
class Band include Mongoid::Document belongs_to:label, counter_cache: true end class Label include Mongoid::Document include Mongoid::Attributes::Dynamic has_many :bands end
Cuando utiliza el módulo Mongoid::Attributes::Dynamic, Mongoid utiliza las mismas reglas de nombres para el campo de contador que cuando declara un campo de contador explícito: por defecto, utiliza un nombre de campo *_count basado en la asociación, a menos que especifique un nombre de campo personalizado con una cadena en la opción counter_cache.
Metadatos de la Asociación
Cuando defines una asociación, Mongoid almacena metadatos sobre esa asociación. Puedes acceder a los metadatos llamando al método reflect_on_association en una clase de modelo o documento, o accediendo directamente a los metadatos en un documento específico. El siguiente ejemplo muestra cómo acceder a los metadatos utilizando el método reflect_on_association y por acceso directo:
# Get the metadata for a named association from the class or document Model.reflect_on_association(:<association_name>) # Directly access metadata on a document model.associations[:<association_name>]
Nota
Reemplace <association_name> en el ejemplo anterior con el nombre de su asociación.
Atributos
Todas las asociaciones contienen atributos que almacenan información sobre el documento relacionado. Las asociaciones contienen los siguientes atributos:
_target:El documento o documentos proxy_base: El documento en el que se define la asociación_association: Información sobre la asociación
El siguiente ejemplo accede a cada uno de los atributos anteriores:
class Band include Mongoid::Document embeds_many :songs end Band.songs = [ song ] Band.songs._target # returns [ song ] Band.songs._base # returns band Band.songs._association # returns the association metadata
La siguiente tabla muestra la información almacenada en el atributo _association:
Método | Descripción |
|---|---|
| El nombre del padre de un hijo polimórfico. |
| Devuelve si existe una opción |
| Devuelve si la asociación se está construyendo automáticamente. |
| Devuelve si la asociación se está guardando automáticamente. |
| Devuelve si la asociación tiene devoluciones de llamada en cascada desde el parent. |
| El nombre de la clase del documento proxy. |
| Devuelve si la asociación es una asociación cíclica. |
| Las dependencias de la asociación. |
| Devuelve |
| Devuelve si la asociación está incrustada en otro documento. |
| Indica si la asociación tiene un inverso |
| El nombre del campo de clave externa. |
| El nombre del método de comprobación de integridad del campo clave foránea. |
| El nombre del establecedor del campo de clave externa. |
| Devuelve si la clave externa está indexada automáticamente. |
| Los nombres de todas las asociaciones inversas. |
| El nombre de una única asociación inversa. |
| El nombre de la clase de la asociación en el lado inverso. |
| El nombre del campo de clave foránea en el lado inverso. |
| La clase de la asociación en el lado inverso. |
| Los metadatos de la asociación en el lado inverso. |
| El nombre definido explícitamente de la asociación inversa. |
| El nombre del método utilizado para establecer el inverso. |
| El nombre del campo de tipo polimórfico de la inversa. |
| El nombre del configurador del campo de tipo polimórfico del inverso. |
| El nombre del campo en el hash del atributo que se usa para obtener la asociación. |
| La clase de los documentos proxy en la asociación. |
| El nombre de la asociación. |
| Devuelve |
| Las opciones de ordenación personalizadas en la asociación. |
| Devuelve si la asociación es polimórfica. |
| El nombre del campo donde se establecerá la asociación. |
| El nombre del atributo en el que se almacenará una asociación incorporada. |
| Devuelve si la asociación tiene una opción de toque. |
| El nombre del campo para obtener el tipo polimórfico. |
| El nombre del campo para establecer el tipo polimórfico. |
| Devuelve si la asociación tiene una validación asociada. |