Skip to content

Commit ef83faf

Browse files
committed
Merge branch 'standardized' of https://github.com/mongodb/docs-mongoid into DOCSP-42762-indexes
2 parents da4cd3b + 4003671 commit ef83faf

File tree

8 files changed

+877
-5
lines changed

8 files changed

+877
-5
lines changed

snooty.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ toc_landing_pages = [
1717
[constants]
1818
rails-6-version = 6.0
1919
rails-7-version = 7.1
20+
rails-8-version-docs = "v8.0"
2021
odm = "Mongoid"
2122
version = "9.0"
2223
full-version = "{+version+}.2"

source/data-modeling.txt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ Model Your Data
1515
:caption: Data Modeling
1616

1717
Documents </data-modeling/documents>
18+
Field Behaviors </data-modeling/field-behaviors>
1819
Inheritance </data-modeling/inheritance>
19-
Nested Attributes </data-modeling/nested-attributes>
20+
Document Validation </data-modeling/validation>
2021

2122
In this section, you can learn how to model data in {+odm+}.
2223

2324
- :ref:`mongoid-modeling-documents`: Learn about the ``Document``
2425
module.
26+
27+
- :ref:`mongoid-field-behaviors`: Learn how to customize the behaviors of fields
28+
in {+odm+} to meet your application requirements.
2529

2630
- :ref:`mongoid-modeling-inheritance`: Learn how to implement
2731
inheritance in your model classes.
2832

29-
- :ref:`mongoid-modeling-nested-attr`: Learn how to modify documents and
30-
their associations in a single operation.
33+
- :ref:`mongoid-modeling-validation`: Learn how to create document
34+
validation rules for your model classes.
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
.. _mongoid-field-behaviors:
2+
3+
=========================
4+
Customize Field Behaviors
5+
=========================
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: customize, attributes, optimize, model, configure, code example
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 1
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to customize the behavior of fields in {+odm+} models.
24+
25+
Specify Default Values
26+
----------------------
27+
28+
You can configure fields to have default values by using the ``default`` option.
29+
Default field values can be either fixed or ``Proc`` values.
30+
31+
The following example specifies a fixed default value for the ``state``
32+
field:
33+
34+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
35+
:language: ruby
36+
:start-after: # start-field-default
37+
:end-before: # end-field-default
38+
39+
The following example specifies a ``Proc`` default value for the ``fulfill_by``
40+
field:
41+
42+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
43+
:language: ruby
44+
:start-after: # start-field-default-processed
45+
:end-before: # end-field-default-processed
46+
47+
.. note::
48+
49+
The driver evaluates default values that are not ``Proc`` instances when the
50+
class *loads*. The driver evaluates ``Proc`` values when the document is
51+
*instantiated*. The following default field values do not produce equivalent outcomes:
52+
53+
.. code-block:: ruby
54+
55+
# Time.now is set to the time the class is loaded
56+
field :submitted_at, type: Time, default: Time.now
57+
58+
# Time.now is set to the time the document is instantiated
59+
field :submitted_at, type: Time, default: ->{ Time.now }
60+
61+
You can set a default value that depends on the document's state by using the
62+
``self`` keyword in a ``Proc`` instance. The following example sets the
63+
``fulfill_by`` default value to depend on the state of the ``submitted_at``
64+
field:
65+
66+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
67+
:language: ruby
68+
:start-after: # start-field-default-self
69+
:end-before: # end-field-default-self
70+
71+
By default, {+odm+} applies ``Proc`` default values after setting and
72+
initializing all other attributes. To apply the default before setting the other
73+
attributes, set the ``pre_processed`` option to ``true``, as shown in the
74+
following example:
75+
76+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
77+
:language: ruby
78+
:start-after: # start-field-default-pre-processed
79+
:end-before: # end-field-default-pre-processed
80+
81+
.. tip::
82+
83+
Always set the ``pre-processed`` option to ``true`` to set a
84+
default ``Proc`` value for the ``_id`` field.
85+
86+
Specify Storage Names
87+
---------------------
88+
89+
You can specify a separate field name to store in the database, while still
90+
referring to the field by its original name in your application. This can save
91+
storage space, because MongoDB stores all field information along
92+
with every document.
93+
94+
You can set an alternate storage name by using the ``as:`` keyword. The
95+
following example creates a field called ``name`` that {+odm+} stores in the database as
96+
``n``:
97+
98+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
99+
:language: ruby
100+
:start-after: # start-field-as
101+
:end-before: # end-field-as
102+
103+
{+odm+} stores the ``name`` field as ``"n"``, but you can still access the field as
104+
``name`` in your application.
105+
106+
Field Aliases
107+
-------------
108+
109+
You can create an alias for your field by using the ``alias_attribute`` option.
110+
Specifying an alias does not change how {+odm+} stores the field in the
111+
database, but it allows you to access the field by a different name in your
112+
application.
113+
114+
The following example specifies an alias for the ``name`` field:
115+
116+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
117+
:language: ruby
118+
:start-after: # start-field-alias
119+
:end-before: # end-field-alias
120+
121+
To remove a field alias, you can use the ``unalias_attribute`` option. The
122+
following example removes the alias for the ``name`` field:
123+
124+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
125+
:language: ruby
126+
:start-after: # start-field-unalias
127+
:end-before: # end-field-unalias
128+
129+
You can also use ``unalias_attribute`` to remove the predefined ``id`` alias from the
130+
``_id`` field. This can be used to store different values in the ``_id`` field
131+
and an ``id`` field.
132+
133+
Field Redefinition
134+
------------------
135+
136+
By default, {+odm+} allows you to redefine fields on a model. To raise an error
137+
when a field is redefined, set the ``duplicate_fields_exception`` configuration
138+
option in your ``mongoid.yml`` file to ``true``.
139+
140+
If the ``duplicate_fields_exception`` option is set to ``true``, you can still
141+
redefine a specific field by setting the ``overwrite`` option to ``true`` when
142+
you define the field. The following example defines the ``name`` field, and then
143+
redefines the field by using the ``overwrite`` option:
144+
145+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
146+
:language: ruby
147+
:start-after: # start-field-overwrite
148+
:end-before: # end-field-overwrite
149+
150+
Custom ID Field
151+
---------------
152+
153+
By default, {+odm+} defines the ``_id`` field on documents to contain a
154+
``BSON::ObjectId`` value that {+odm+} generates automatically. You can customize
155+
the type or specify the default value of the ``_id`` field by specifying it in your
156+
model.
157+
158+
The following example creates a ``Band`` class with a custom ``_id`` field:
159+
160+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
161+
:language: ruby
162+
:start-after: # start-custom-id
163+
:end-before: # end-custom-id
164+
165+
You can omit the default value for the ``_id`` field. If you don't specify a
166+
default value for the field, {+odm+} persists the document without an ``_id``
167+
value. For top-level documents, the MongoDB server automatically
168+
assigns an ``_id`` value. However, for embedded documents, the server does not
169+
assign an ``_id`` value.
170+
171+
When you don't specify a value for the ``_id`` field, {+odm+} does not retrieve
172+
the automatically assigned value from the server. Because of this, you cannot
173+
retrieve the document from the database by using the ``_id`` value.
174+
175+
Uncastable Values
176+
-----------------
177+
178+
A value is considered **uncastable** if it cannot be converted to the specified
179+
field type. For example, an array is considered uncastable when assigned to an
180+
``Integer`` field.
181+
182+
In v8.0 and later, {+odm+} assigns ``nil`` to values that are uncastable. The
183+
original uncastable value is stored in the ``attributes_before_type_cast`` hash
184+
with their field names.
185+
186+
Custom Getters and Setters
187+
--------------------------
188+
189+
You can override the default getter and setter methods for a field by specifying
190+
a method with the same name as the field and calling the ``read_attribute`` or
191+
``write_attribute`` method to operate on the raw attribute value.
192+
193+
The following example creates a custom getter and setter for the ``name`` field
194+
of a ``Person`` class:
195+
196+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
197+
:language: ruby
198+
:start-after: # start-custom-getter-setter
199+
:end-before: # end-custom-getter-setter
200+
201+
Read-Only Attributes
202+
--------------------
203+
204+
You can specify a field to be read-only by specifying the ``attr_readonly`` option.
205+
This allows you to create documents with the attributes, but not update them.
206+
207+
The following example creates a ``Band`` class and specifies the ``name`` field
208+
as read-only:
209+
210+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
211+
:language: ruby
212+
:start-after: # start-read-only
213+
:end-before: # end-read-only
214+
215+
If you call a mass-update method, such as ``update_attributes``, and pass in a
216+
read-only field, {+odm+} ignores the read-only field and updates all others. If
217+
you attempt to explicitly update a read-only field, {+odm+} raises a
218+
``ReadonlyAttribute`` exception.
219+
220+
.. note::
221+
222+
Calls to atomic persistence operators, such as ``bit`` and ``inc``, still
223+
persist changes to the read-only field.
224+
225+
Localize Fields
226+
---------------
227+
228+
{+odm+} supports localized fields by using the `i18n gem
229+
<https://github.com/ruby-i18n/i18n>`__. When you localize a field, {+odm+}
230+
stores the field as a hash of locale keys and values. Accessing the fields
231+
behaves in the same way as a string value. You can localize fields of any field
232+
type.
233+
234+
The following example creates a ``Product`` class with a localized ``review``
235+
field:
236+
237+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
238+
:language: ruby
239+
:start-after: # start-localized-field
240+
:end-before: # end-localized-field
241+
242+
You can get and set all translations at once by calling the ``_translations``
243+
method:
244+
245+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
246+
:language: ruby
247+
:start-after: # start-localized-translations
248+
:end-before: # end-localized-translations
249+
250+
You can specify fallbacks for localized fields by enabling the `i18n fallbacks
251+
<https://github.com/ruby-i18n/i18n/wiki/Fallbacks>`__ feature.
252+
253+
Enable fallbacks in a Rails application by setting the ``config.i18n.fallbacks``
254+
configuration setting in your environment and setting the fallback languages:
255+
256+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
257+
:language: ruby
258+
:start-after: # start-localized-fallbacks
259+
:end-before: # end-localized-fallbacks
260+
261+
Enable fallbacks in non-Rails applications by including the module into the i18n
262+
backend and setting the fallback languages:
263+
264+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
265+
:language: ruby
266+
:start-after: # start-localized-fallbacks-non-rails
267+
:end-before: # end-localized-fallbacks-non-rails
268+
269+
After enabling fallbacks, if an active language does not have have a
270+
translation, it is looked up in the specified fallback language.
271+
272+
You can disable fallback languages for a specified field by setting the
273+
``fallbacks`` option to false when defining the field:
274+
275+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
276+
:language: ruby
277+
:start-after: # start-localized-no-fallbacks
278+
:end-before: # end-localized-no-fallbacks
279+
280+
When querying localized fields, {+odm+} automatically alters the query criteria
281+
to match the current locale. The following example queries the ``Product`` class
282+
for a review in the ``en`` locale:
283+
284+
.. literalinclude:: /includes/data-modeling/field-behaviors.rb
285+
:language: ruby
286+
:start-after: # start-localized-query
287+
:end-before: # end-localized-query
288+
289+
.. note::
290+
291+
If you want to query extensively on localized fields, we recommend indexing
292+
each locale that you want to query on.

0 commit comments

Comments
 (0)