Relations¶
On this page
Common Behaviour¶
Attributes¶
All relations contain a _target
, which is the proxied document or documents, a _base
which is the document the relation hangs off, and _association
which provides information
about the relation.
Extensions¶
All relations can have extensions, which provides a way to add application specific functionality to the relation. They are defined by providing a block to the relation definition.
Custom Relation Names¶
You can name your relations whatever you like, but if the class cannot be inferred by Mongoid from the name, and neither can the opposite side you’ll want to provide the macro with some additional options to tell Mongoid how to hook them up.
Custom Primary & Foreign Keys¶
The fields used when looking up associations can be explicitly specified.
The default is to use id
on the “parent” association and #{association_name}_id
on the “child” association, for example with a has_many/belongs_to:
Specify a different primary_key
to change the field name on the “parent”
association and foreign_key
to change the field name on the “child”
association:
With a has_and_belongs_to_many association, primary key is the field on the remote model that contains the value by which the remote model is looked up, and foreign key is the field on the local model which stores these values. For example:
Note that just like with the default #{association_name}_id
field,
Mongoid automatically adds a field for the custom foreign key c_ref
to
the model. However, since Mongoid doesn’t know what type of data should be
allowed in the field, the field is created with a type of Object. It is a
good idea to explicitly define the field with the appropriate type.
Validations¶
It is important to note that by default, Mongoid will validate the children of any
relation that are loaded into memory via a validates_associated
. The relations that
this applies to are:
embeds_many
embeds_one
has_many
has_one
has_and_belongs_to_many
If you do not want this behavior, you may turn it off when defining the relation.
Polymorphism¶
One to one and one to many associations support polymorphism, which is having a single association potentially contain objects of different classes. For example, we could model an organization in which departments and teams have managers as follows:
To provide another example, suppose we want to track price history for products and bundles. This can be achieved via an embedded one to many polymorphic association:
To define a polymorphic association, specify the polymorphic: true
option
on the child association and add the as: :association_name
option to the
parent association.
Note that Mongoid currently supports polymorphism only in one direction - from the child to the parent. For example, polymorphism cannot be used to specify that a bundle may contain other bundles or products:
has_and_belongs_to_many
associations do not support polymorphism.
Cascading Callbacks¶
If you want the embedded document callbacks to fire when calling a persistence operation on its parent, you will need to provide the cascade callbacks option to the relation.
Dependent Behaviour¶
You can provide dependent options to referenced associations to instruct Mongoid how to handle situations where one side of the relation is deleted, or is attempted to be deleted. The options are as follows:
:delete
: Delete the child document without running any of the model callbacks.:destroy
: Destroy the child document and run all of the model callbacks.:nullify
: Orphan the child document.:restrict
: Raise an error if the child is not empty.
The default behavior of each association when no dependent option is provided is to nullify.
Autosaving¶
One core difference between Mongoid and Active Record from a behavior standpoint is that Mongoid does not automatically save child relations for relational associations. This is for performance reasons.
To enable an autosave on a relational association (embedded associations do not need this since they are actually part of the parent in the database) add the autosave option to the relation.
Note that autosave functionality will automatically be added to a relation when using
accepts_nested_attributes_for
or validating presence of the relation.
Recursive Embedding¶
A document can recursively embed itself using recursively_embeds_one
or recursively_embeds_many
,
which provides accessors for the parent and children via parent_
and child_
methods.
Existence Predicates¶
All relations have existence predicates on them in the form of name?
and has_name?
to check if the relation is blank.
Autobuilding¶
One to one relations (embeds_one
, has_one
) have an autobuild option which tells
Mongoid to instantiate a new document when the relation is accessed and it is nil
.
Touching¶
Any belongs_to
relation, no matter where it hangs off from, can take an optional :touch
option which will call the touch method on it and any parent relations with the option defined
when the base document calls #touch
.
Association metadata¶
All relations in Mongoid contain metadata that holds information about the relation in question, and is a valuable tool for third party developers to use to extend Mongoid.
You can access the association metadata of the relation in a few different ways.
The Association Object¶
The association object itself contains more information than one might know what to do with, and is useful for developers of extensions to Mongoid.
Method | Description |
---|---|
Association#as |
Returns the name of the parent to a polymorphic child. |
Association#as? |
Returns whether or not an as option exists. |
Association#autobuilding? |
Returns whether or not the relation is autobuilding. |
Association#autosaving? |
Returns whether or not the relation is autosaving. |
Association#cascading_callbacks? |
Returns whether the relation has callbacks cascaded down from the parent. |
Association#class_name |
Returns the class name of the proxied document. |
Association#cyclic? |
Returns whether the relation is a cyclic relation. |
Association#dependent |
Returns the relation’s dependent option. |
Association#destructive? |
Returns true if the relation has a dependent delete or destroy. |
Association#embedded? |
Returns whether the relation is embedded in another document. |
Association#forced_nil_inverse? |
Returns whether the relation has a nil inverse defined. |
Association#foreign_key |
Returns the name of the foreign key field. |
Association#foreign_key_check |
Returns the name of the foreign key field dirty check method. |
Association#foreign_key_setter |
Returns the name of the foreign key field setter. |
Association#indexed? |
Returns whether the foreign key is auto indexed. |
Association#inverses |
Returns the names of all inverse relation. |
Association#inverse |
Returns the name of a single inverse relation. |
Association#inverse_class_name |
Returns the class name of the relation on the inverse side. |
Association#inverse_foreign_key |
Returns the name of the foreign key field on the inverse side. |
Association#inverse_klass |
Returns the class of the relation on the inverse side. |
Association#inverse_association |
Returns the metadata of the association on the inverse side. |
Association#inverse_of |
Returns the explicitly defined name of the inverse relation. |
Association#inverse_setter |
Returns the name of the method used to set the inverse. |
Association#inverse_type |
Returns the name for the polymorphic type field of the inverse. |
Association#inverse_type_setter |
Returns the name for the polymorphic type field setter of the inverse. |
Association#key |
Returns the name of the field in the attributes hash to use to get the relation. |
Association#klass |
Returns the class of the proxied documents in the relation. |
Association#name |
Returns the relation name. |
Association#options |
Returns self, for API compatibility with Active Record. |
Association#order |
Returns the custom sorting options on the relation. |
Association#polymorphic? |
Returns whether the relation is polymorphic. |
Association#setter |
Returns the name of the field to set the relation. |
Association#store_as |
Returns the name of the attribute to store an embedded relation in. |
Association#touchable? |
Returns whether or not the relation has a touch option. |
Association#type |
Returns the name of the field to get the polymorphic type. |
Association#type_setter |
Returns the name of the field to set the polymorphic type. |
Association#validate? |
Returns whether the relation has an associated validation. |
Embeds One¶
One to one relationships where the children are embedded in the parent document are defined
using Mongoid’s embeds_one
and embedded_in
macros.
Defining¶
The parent document of the relation should use the embeds_one
macro to indicate is has 1
embedded child, where the document that is embedded uses embedded_in
. Definitions are required
on both sides to the relation in order for it to work properly.
Storage¶
Documents that are embedded using the embeds_one
macro are stored as a hash inside the
parent in the parent’s database collection.
You can optionally tell Mongoid to store the embedded document in a different attribute other
than the name, by providing a :store_as
option.
Embeds Many¶
One to many relationships where the children are embedded in the parent document are defined
using Mongoid’s embeds_many
and embedded_in
macros.
Defining¶
The parent document of the relation should use the embeds_many
macro to indicate it has n
number of embedded children, where the document that is embedded uses embedded_in
. Definitions
are required on both sides to the relation in order for it to work properly.
Storage¶
Documents that are embedded using the embeds_many
macro are stored as an array of hashes
inside the parent in the parent’s database collection.
You can optionally tell Mongoid to store the embedded document in a different attribute other
than the name, by providing a :store_as
option.
Has One¶
One to one relationships where the children are referenced in the parent document are defined
using Mongoid’s has_one
and belongs_to
macros.
Defining¶
The parent document of the relation should use the has_one
macro to indicate is has 1 referenced
child, where the document that is referenced in it uses belongs_to
.
Definitions are required on both sides to the relation in order for it to work properly, unless one of the models is embedded.
Storage¶
When defining a relation of this nature, each document is stored in its respective collection, but the child document contains a “foreign key” reference to the parent.
Has Many¶
One to many relationships where the children are stored in a separate collection from the parent
document are defined using Mongoid’s has_many
and belongs_to
macros. This exhibits similar
behavior to Active Record.
Defining¶
The parent document of the relation should use the has_many
macro to indicate is has n number
of referenced children, where the document that is referenced uses belongs_to
.
Definitions are required on both sides to the relation in order for it to work properly, unless one of the models is embedded.
Storage¶
When defining a relation of this nature, each document is stored in its respective collection, but the child document contains a “foreign key” reference to the parent.
Belongs To¶
A belongs_to
macro is used when a document is the child in a has_one
or has_many
association.
By default, a child document cannot be saved unless it’s associated with a parent. To override this requirement,
you can use the option, optional: false
.
Defining¶
The child document of the relation uses the belongs_to
macro to indicate it is associated with a parent.
The document on the belongs_to
side stores the reference to the parent.
Definitions are required on both sides to the relation in order for it to work properly, unless one of the models is embedded.
Storage¶
When defining a relation of this nature, each document is stored in its respective collection, but the child document contains a “foreign key” reference to the parent.
Has And Belongs To Many¶
Many to many relationships where the inverse documents are stored in a separate collection
from the base document are defined using Mongoid’s has_and_belongs_to_many
macro. This
exhibits similar behavior to Active Record with the exception that no join collection is needed,
the foreign key ids are stored as arrays on either side of the relation.
Defining¶
Both sides of the relation use the same macro.
You can create a one sided many to many if you want to mimic a has_many that stores the keys as an array on the parent.
Storage¶
When defining a relation of this nature, each document is stored in its respective collection, and each document contains a “foreign key” reference to the other in the form of an array.
The counter_cache option¶
As with ActiveRecord, the :counter_cache option can be used on a relation to make finding the
number of belonging objects more efficient. Also similar to ActiveRecord, you must take into
account that there will be an extra attribute on the associated model. This means that with Mongoid,
you need to include Mongoid::Attributes::Dynamic
on the associated model.
For example: