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
/ /

Utilizar asociaciones de datos

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.

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_one

  • has_many

  • belongs_to

  • has_and_belongs_to_many

Las siguientes secciones describen cómo utilizar cada uno de estos tipos de asociación.

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.

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.

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

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

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.

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)

Puede usar asociaciones integradas para almacenar diferentes tipos de documentos en la misma colección. Mongoid admite asociaciones integradas con las siguientes macros:

  • embeds_one

  • embeds_many

  • embedded_in

  • recursively_embeds_one

  • recursively_embeds_many

Las siguientes secciones describen cómo emplear estos tipos de asociación.

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

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

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

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:

  • Mongoid expande los argumentos Range a hashes con condiciones $gte y $lte. Esto puede generar consultas no válidas en algunos casos y generar una excepción InvalidQuery.

  • 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.

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.

Puede eliminar documentos secundarios de las asociaciones embeds_many mediante uno de los siguientes métodos:

  • clear

  • delete_all

  • destroy_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

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.

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"

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

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

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.

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_many

  • embeds_one

  • has_many

  • has_one

  • has_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

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.

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.

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 en nil. 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 retorna false si 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

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.

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

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.

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 llama Band, el nombre del campo de contador por defecto es bands_count.

  • Un string o symbol: 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::Dynamic en 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.

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.

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

Association#as

El nombre del padre de un hijo polimórfico.

Association#as?

Devuelve si existe una opción as.

Association#autobuilding?

Devuelve si la asociación se está construyendo automáticamente.

Association#autosaving?

Devuelve si la asociación se está guardando automáticamente.

Association#cascading_callbacks?

Devuelve si la asociación tiene devoluciones de llamada en cascada desde el parent.

Association#class_name

El nombre de la clase del documento proxy.

Association#cyclic?

Devuelve si la asociación es una asociación cíclica.

Association#dependent

Las dependencias de la asociación.

Association#destructive?

Devuelve true si la asociación tiene un método de eliminación o destrucción dependiente.

Association#embedded?

Devuelve si la asociación está incrustada en otro documento.

Association#forced_nil_inverse?

Indica si la asociación tiene un inverso nil definido.

Association#foreign_key

El nombre del campo de clave externa.

Association#foreign_key_check

El nombre del método de comprobación de integridad del campo clave foránea.

Association#foreign_key_setter

El nombre del establecedor del campo de clave externa.

Association#indexed?

Devuelve si la clave externa está indexada automáticamente.

Association#inverses

Los nombres de todas las asociaciones inversas.

Association#inverse

El nombre de una única asociación inversa.

Association#inverse_class_name

El nombre de la clase de la asociación en el lado inverso.

Association#inverse_foreign_key

El nombre del campo de clave foránea en el lado inverso.

Association#inverse_klass

La clase de la asociación en el lado inverso.

Association#inverse_association

Los metadatos de la asociación en el lado inverso.

Association#inverse_of

El nombre definido explícitamente de la asociación inversa.

Association#inverse_setter

El nombre del método utilizado para establecer el inverso.

Association#inverse_type

El nombre del campo de tipo polimórfico de la inversa.

Association#inverse_type_setter

El nombre del configurador del campo de tipo polimórfico del inverso.

Association#key

El nombre del campo en el hash del atributo que se usa para obtener la asociación.

Association#klass

La clase de los documentos proxy en la asociación.

Association#name

El nombre de la asociación.

Association#options

Devuelve self, para compatibilidad de API con ActiveRecord.

Association#order

Las opciones de ordenación personalizadas en la asociación.

Association#polymorphic?

Devuelve si la asociación es polimórfica.

Association#setter

El nombre del campo donde se establecerá la asociación.

Association#store_as

El nombre del atributo en el que se almacenará una asociación incorporada.

Association#touchable?

Devuelve si la asociación tiene una opción de toque.

Association#type

El nombre del campo para obtener el tipo polimórfico.

Association#type_setter

El nombre del campo para establecer el tipo polimórfico.

Association#validate?

Devuelve si la asociación tiene una validación asociada.

Volver

función de retorno