Skip to content

Commit 18d1c10

Browse files
p-mongop
andauthored
MONGOID-4962 Clarify storage of referenced associations (#4949)
Co-authored-by: Oleg Pudeyev <[email protected]>
1 parent 6eaab72 commit 18d1c10

File tree

1 file changed

+118
-111
lines changed

1 file changed

+118
-111
lines changed

source/tutorials/mongoid-relations.txt

Lines changed: 118 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -20,98 +20,100 @@ Mongoid supports the ``has_one``, ``has_many``, ``belongs_to`` and
2020
Has One
2121
-------
2222

23-
One to one associations where documents are stored in separate collections
24-
are defined using ``has_one`` and ``belongs_to`` macros.
25-
26-
Defining
27-
````````
28-
29-
The parent document of the association should use the ``has_one`` macro to
30-
indicate is has one referenced child, and the document that is referenced
31-
should use ``belongs_to``.
23+
Use the ``has_one`` macro to declare that the parent has a child stored in
24+
a separate collection. The child is optional by default:
3225

3326
.. code-block:: ruby
3427

3528
class Band
3629
include Mongoid::Document
30+
3731
has_one :studio
3832
end
3933

34+
When using ``has_one``, the child model must use ``belongs_to`` to declare the
35+
association with the parent:
36+
37+
.. code-block:: ruby
38+
4039
class Studio
4140
include Mongoid::Document
42-
field :name, type: String
41+
4342
belongs_to :band
4443
end
4544

46-
Definitions are required on both sides to the association in order for it to
47-
work properly.
45+
Given the above definitions, every child document contains a reference to
46+
its respective parent document:
4847

49-
Storage
50-
```````
48+
.. code-block:: ruby
5149

52-
When defining an association of this nature, each document is stored in its
53-
respective collection, and the child document contains a "foreign key"
54-
reference to the parent:
50+
band = Band.create!(studio: Studio.new)
51+
# => #<Band _id: 600114fa48966848ad5bd392, >
5552

56-
.. code-block:: ruby
53+
band.studio
54+
# => #<Studio _id: 600114fa48966848ad5bd391, band_id: BSON::ObjectId('600114fa48966848ad5bd392')>
5755

58-
# The parent band document.
59-
{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }
56+
Use validations to require that the child is present:
6057

61-
# The child studio document.
62-
{
63-
"_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
64-
"band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
65-
}
58+
.. code-block:: ruby
59+
60+
class Band
61+
include Mongoid::Document
62+
63+
has_one :studio
64+
65+
validates_presence_of :studio
66+
end
6667

6768

6869
Has Many
6970
--------
7071

71-
One to many associations where the children are stored in a separate
72-
collection from the parent document are defined using Mongoid's ``has_many``
73-
and ``belongs_to`` macros.
74-
75-
Defining
76-
````````
77-
78-
The parent document of the association should use the ``has_many`` macro to
79-
indicate is has n number of referenced children, where the document that is
80-
referenced uses ``belongs_to``.
72+
Use the ``has_many`` association to declare that the parent has zero or more
73+
children stored in a separate collection:
8174

8275
.. code-block:: ruby
8376

8477
class Band
8578
include Mongoid::Document
79+
8680
has_many :members
8781
end
8882

83+
Like with ``has_one``, the child model must use ``belongs_to`` to declare the
84+
association with the parent:
85+
86+
.. code-block:: ruby
87+
8988
class Member
9089
include Mongoid::Document
91-
field :name, type: String
90+
9291
belongs_to :band
9392
end
9493

95-
Definitions are required on both sides to the association in order for it
96-
to work properly.
94+
Also as with ``has_one``, the child documents contain references to their
95+
respective parents:
9796

98-
Storage
99-
```````
97+
.. code-block:: ruby
98+
99+
band = Band.create!(members: [Member.new])
100+
# => #<Band _id: 6001166d4896684910b8d1c5, >
100101

101-
When defining an association of this nature, each document is stored in its
102-
respective collection, and the child document contains a "foreign key"
103-
reference to the parent.
102+
band.members
103+
# => [#<Member _id: 6001166d4896684910b8d1c6, band_id: BSON::ObjectId('6001166d4896684910b8d1c5')>]
104+
105+
Use validations to require that at least one child is present:
104106

105107
.. code-block:: ruby
106108

107-
# The parent band document.
108-
{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }
109+
class Band
110+
include Mongoid::Document
111+
112+
has_many :members
113+
114+
validates_presence_of :members
115+
end
109116

110-
# A child member document.
111-
{
112-
"_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
113-
"band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
114-
}
115117

116118
Queries
117119
```````
@@ -204,117 +206,122 @@ The following examle illustrates the difference between ``exists?`` and
204206
Belongs To
205207
----------
206208

207-
A ``belongs_to`` macro is used when a document is the child in a ``has_one``
208-
or ``has_many`` association. By default, in order for a document to
209-
be saved, each of its ``belongs_to`` associations must be provided a value.
210-
To override this requirement for a particular association, use the option
211-
``optional: false`` on the ``belong_to`` association. To override this
212-
requirement globally, set the ``belongs_to_required_by_default``
213-
:ref:`configuration option <configuration-options>` to ``false``.
209+
Use the ``belongs_to`` macro to associate a child with a parent stored in a
210+
separate collection. The ``_id`` of the parent (if a parent is associated)
211+
is stored in the child.
214212

215-
Defining
216-
````````
217-
218-
The child document of the association uses the ``belongs_to`` macro to indicate
219-
it is associated with a parent. The document on the ``belongs_to`` side
220-
stores the reference to the parent.
213+
By default, if a ``belongs_to`` association is defined on a model, it must be
214+
provided a value for a model instance to be saved. Use the ``optional: true```
215+
option to make the instances persistable without specifying the parent:
221216

222217
.. code-block:: ruby
223218

224219
class Band
225220
include Mongoid::Document
221+
226222
has_one :studio
227223
end
228224

229225
class Studio
230226
include Mongoid::Document
231-
field :name, type: String
232-
belongs_to :band
227+
228+
belongs_to :band, optional: true
233229
end
230+
231+
studio = Studio.create!
232+
# => #<Studio _id: 600118184896684987aa884f, band_id: nil>
234233

235-
Definitions are required on both sides to the association in order for it to
236-
work properly.
237-
238-
Storage
239-
```````
234+
To change the default behavior of ``belongs_to`` associations to not require
235+
their respective parents globally, set the ``belongs_to_required_by_default``
236+
:ref:`configuration option <configuration-options>` to ``false``.
240237

241-
When defining an association of this nature, each document is stored in its respective collection,
242-
but the child document contains a "foreign key" reference to the parent.
238+
Although ``has_one`` and ``has_many`` associations require the
239+
corresponding ``belongs_to`` association to be defined on the child,
240+
``belongs_to`` may also be used without a corresponding ``has_one`` or
241+
``has_many`` macro. In this case the child is not accessible from the parent
242+
but the parent is accessible from the child:
243243

244244
.. code-block:: ruby
245245

246-
# The parent band document.
247-
{ "_id" : ObjectId("4d3ed089fb60ab534684b7e9") }
246+
class Band
247+
include Mongoid::Document
248+
end
248249

249-
# The child studio document.
250-
{
251-
"_id" : ObjectId("4d3ed089fb60ab534684b7f1"),
252-
"band_id" : ObjectId("4d3ed089fb60ab534684b7e9")
253-
}
250+
class Studio
251+
include Mongoid::Document
252+
253+
belongs_to :band
254+
end
254255

255-
Has And Belongs To Many
256-
-----------------------
256+
For clarity it is possible to add the ``inverse_of: nil`` option in cases when
257+
the parent does not define the association:
257258

258-
Many to many associations in Mongoid are defined using the
259-
``has_and_belongs_to_many`` macro. Unlike ActiveRecord's
260-
``has_and_belongs_to_many``, in Mongoid there is no "join collection" -
261-
the foreign key ids are stored as arrays on both sides of the association.
259+
.. code-block:: ruby
262260

263-
``has_and_belongs_to_many`` association has no embedded equivalent.
261+
class Band
262+
include Mongoid::Document
263+
end
264+
265+
class Studio
266+
include Mongoid::Document
267+
268+
belongs_to :band, inverse_of: nil
269+
end
264270

265-
Defining
266-
````````
267271

268-
Both sides of the association use the same macro.
272+
Has And Belongs To Many
273+
-----------------------
274+
275+
Use the ``has_and_belongs_to_many`` macro to declare a many-to-many
276+
association:
269277

270278
.. code-block:: ruby
271279

272280
class Band
273281
include Mongoid::Document
282+
274283
has_and_belongs_to_many :tags
275284
end
276285

277286
class Tag
278287
include Mongoid::Document
279-
field :name, type: String
288+
280289
has_and_belongs_to_many :bands
281290
end
282291

283-
You can create a one sided many to many if you want to mimic a has_many
284-
that stores the keys as an array on the parent.
292+
Both model instances store a list of ids of the associated models, if any:
293+
294+
.. code-block:: ruby
295+
296+
band = Band.create!(tags: [Tag.create!])
297+
# => #<Band _id: 60011d554896684b8b910a2a, tag_ids: [BSON::ObjectId('60011d554896684b8b910a29')]>
298+
299+
band.tags
300+
# => [#<Tag _id: 60011d554896684b8b910a29, band_ids: [BSON::ObjectId('60011d554896684b8b910a2a')]>]
301+
302+
You can create a one-sided ``has_and_belongs_to_many`` association to store
303+
the ids only in one document using the ``inverse_of: nil`` option:
285304

286305
.. code-block:: ruby
287306

288307
class Band
289308
include Mongoid::Document
309+
290310
has_and_belongs_to_many :tags, inverse_of: nil
291311
end
292312

293313
class Tag
294314
include Mongoid::Document
295-
field :name, type: String
296315
end
297316

298-
Storage
299-
```````
300-
301-
When defining an association of this nature, each document is stored in its
302-
respective collection, and each document contains a "foreign key" reference
303-
to the other in the form of an array.
317+
band = Band.create!(tags: [Tag.create!])
318+
# => #<Band _id: 60011dbc4896684bbbaa9255, tag_ids: [BSON::ObjectId('60011dbc4896684bbbaa9254')]>
304319

305-
.. code-block:: ruby
320+
band.tags
321+
# => [#<Tag _id: 60011dbc4896684bbbaa9254, >]
306322

307-
# The band document.
308-
{
309-
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
310-
"tag_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
311-
}
312-
313-
# The tag document.
314-
{
315-
"_id" : ObjectId("4d3ed089fb60ab534684b7f2"),
316-
"band_ids" : [ ObjectId("4d3ed089fb60ab534684b7e9") ]
317-
}
323+
A one-sided ``has_and_belongs_to_many`` association is, naturally, only
324+
usable from the model where it is defined.
318325

319326

320327
Querying Referenced Associations

0 commit comments

Comments
 (0)