Skip to content

Commit 4003671

Browse files
authored
DOCSP-45363: validation (#73)
* DOCSP-45363: validation * keywords * wip * SA PR fixes 1
1 parent a436575 commit 4003671

File tree

6 files changed

+445
-8
lines changed

6 files changed

+445
-8
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: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ Model Your Data
1313

1414
.. toctree::
1515
:caption: Data Modeling
16-
17-
In this section, you can learn how to model data in {+odm+}.
18-
16+
1917
Documents </data-modeling/documents>
2018
Field Behaviors </data-modeling/field-behaviors>
2119
Inheritance </data-modeling/inheritance>
22-
Nested Attributes </data-modeling/nested-attributes>
20+
Document Validation </data-modeling/validation>
21+
22+
In this section, you can learn how to model data in {+odm+}.
2323

2424
- :ref:`mongoid-modeling-documents`: Learn about the ``Document``
2525
module.
@@ -30,5 +30,5 @@ In this section, you can learn how to model data in {+odm+}.
3030
- :ref:`mongoid-modeling-inheritance`: Learn how to implement
3131
inheritance in your model classes.
3232

33-
- :ref:`mongoid-modeling-nested-attr`: Learn how to modify documents and
34-
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: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
.. _mongoid-modeling-validation:
2+
3+
===================
4+
Document Validation
5+
===================
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: ruby framework, odm, schema, code example
13+
14+
.. contents:: On this page
15+
:local:
16+
:backlinks: none
17+
:depth: 2
18+
:class: singlecol
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to define **validation rules** in your
24+
{+odm+} models. After you implement validation into your models, {+odm+}
25+
prevents you from running write operations that violate the validation
26+
rules. Use document validation to restrict data types and value ranges
27+
of document fields in your collections.
28+
29+
{+odm+} includes ``ActiveModel::Validations`` from Active Record to
30+
provide validation functionality, including an associated and uniqueness
31+
validator. To learn more, see the `Active Record Validations
32+
<https://guides.rubyonrails.org/active_record_validations.html>`__
33+
Rails guide and `ActiveModel::Validations
34+
<https://api.rubyonrails.org/classes/ActiveModel/Validations.html>`__
35+
Rails API documentation.
36+
37+
.. note:: Comparing {+odm+} and MongoDB Validation
38+
39+
Validation in {+odm+} applies only in the context of your
40+
application and differs from creating schema validation rules in
41+
MongoDB. This means that your validation rules do not apply to write
42+
operations that are performed outside of your application. To learn
43+
more about MongoDB schema validation, see :manual:`Schema Validation
44+
</core/schema-validation/>` in the {+server-manual+}.
45+
46+
Validation Helpers
47+
------------------
48+
49+
{+odm+} supports Active Record validation helpers that you can use when defining your
50+
model classes. You can use these helpers to set common validation rules
51+
in your application, such as checking for the presence of a field,
52+
comparing a field value to a specified value, or ensuring that a field
53+
has a unique value.
54+
55+
Define a Validation Rule
56+
~~~~~~~~~~~~~~~~~~~~~~~~
57+
58+
Use the ``validates`` macro to create a validation rule, then include
59+
the validation helper and the required specifications for the rule.
60+
61+
.. tip::
62+
63+
Each validation helper accepts one or more field names, which allows you
64+
to define the same rule for multiple fields.
65+
66+
The following code demonstrates how to use the ``presence`` validation
67+
helper to require that ``Person`` instances contain a value for the
68+
``name`` field:
69+
70+
.. literalinclude:: /includes/data-modeling/validation.rb
71+
:start-after: start-simple-val
72+
:end-before: end-simple-val
73+
:language: ruby
74+
:emphasize-lines: 5
75+
:dedent:
76+
77+
You can learn about other useful validation helpers in the
78+
:ref:`mongoid-common-validations` section of this guide.
79+
80+
.. _mongoid-common-validations:
81+
82+
Common Validations
83+
------------------
84+
85+
In this section, you can learn about the following common validation
86+
rules and view examples that use validation helpers:
87+
88+
- :ref:`mongoid-compare-validation`
89+
- :ref:`mongoid-format-validation`
90+
- :ref:`mongoid-inclusion-exclusion-validation`
91+
- :ref:`mongoid-presence-absence-validation`
92+
- :ref:`mongoid-uniqueness-validation`
93+
- :ref:`mongoid-association-validation`
94+
- :ref:`mongoid-other-validation`
95+
96+
.. _mongoid-compare-validation:
97+
98+
Comparison Rule
99+
~~~~~~~~~~~~~~~
100+
101+
You can use the ``comparison`` helper to validate a document based on
102+
the value of a specified field.
103+
104+
The ``comparison`` helper supports the following options:
105+
106+
- ``greater_than``: The value must be greater than the supplied value.
107+
- ``greater_than_or_equal_to``: The value must be greater than or equal to the supplied value.
108+
- ``equal_to``: The value must be equal to the supplied value.
109+
- ``less_than``: The value must be less than the supplied value.
110+
- ``less_than_or_equal_to``: The value must be less than or equal to the supplied value.
111+
- ``other_than``: The value must be different than the supplied value.
112+
113+
This example defines the following comparison validation rules on the
114+
``Order`` model:
115+
116+
- ``delivery_date``: Must be after (greater than) the value of ``order_date``
117+
- ``quantity``: Must be less than ``5``
118+
119+
.. literalinclude:: /includes/data-modeling/validation.rb
120+
:start-after: start-comparison
121+
:end-before: end-comparison
122+
:language: ruby
123+
:emphasize-lines: 8-9
124+
:dedent:
125+
126+
.. _mongoid-format-validation:
127+
128+
Formatting Rule
129+
~~~~~~~~~~~~~~~
130+
131+
You can use the ``format`` helper to validate a document based on
132+
whether a field value matches a regular expression. Use the ``with``
133+
option to specify the regular expression.
134+
135+
This example defines a format validation rule on the
136+
``User`` model to ensure that the ``username`` field contains only
137+
letters:
138+
139+
.. literalinclude:: /includes/data-modeling/validation.rb
140+
:start-after: start-fmt
141+
:end-before: end-fmt
142+
:language: ruby
143+
:emphasize-lines: 6
144+
:dedent:
145+
146+
.. tip:: Alternative Helper Method
147+
148+
The ``Mongoid::Document`` module provides macro methods for certain
149+
validations. Instead of using the ``format`` validation helper in the
150+
``validates`` macro statement, you can use the
151+
``validates_format_of`` method, as shown in the following code:
152+
153+
.. code-block:: ruby
154+
155+
validates_format_of :username, with: /\A[a-zA-Z]+\z/
156+
157+
.. _mongoid-inclusion-exclusion-validation:
158+
159+
Inclusion or Exclusion Rule
160+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
161+
162+
You can use the ``inclusion`` and ``exclusion`` helpers to validate a
163+
document based on whether a field value is in a specified list
164+
of values. Use the ``in`` option to specify the list of values.
165+
166+
This example defines an inclusion validation rule on the
167+
``Order`` model to ensure that the ``shipping`` field value is one of
168+
the accepted values:
169+
170+
.. literalinclude:: /includes/data-modeling/validation.rb
171+
:start-after: start-inclusion
172+
:end-before: end-inclusion
173+
:language: ruby
174+
:emphasize-lines: 6
175+
:dedent:
176+
177+
.. _mongoid-presence-absence-validation:
178+
179+
Presence or Absence Rule
180+
~~~~~~~~~~~~~~~~~~~~~~~~
181+
182+
You can use the ``presence`` and ``absence`` helpers to validate a
183+
document based on whether a field value is present or absent (empty).
184+
185+
This example defines an absence validation rule on the
186+
``Order`` model to ensure that the ``delivery_date`` field value is
187+
either ``nil`` or an empty string:
188+
189+
.. literalinclude:: /includes/data-modeling/validation.rb
190+
:start-after: start-absence
191+
:end-before: end-absence
192+
:language: ruby
193+
:emphasize-lines: 6
194+
:dedent:
195+
196+
.. tip:: Alternative Helper Method
197+
198+
The ``Mongoid::Document`` module provides macro methods for certain
199+
validations. Instead of using the ``presence`` validation helper in the
200+
``validates`` macro statement, you can use the
201+
``validates_presence_of`` method, as shown in the following code:
202+
203+
.. code-block:: ruby
204+
205+
validates_presence_of :delivery_date
206+
207+
.. _mongoid-uniqueness-validation:
208+
209+
Uniqueness Rule
210+
~~~~~~~~~~~~~~~
211+
212+
You can use the ``uniqueness`` helper to validate a
213+
document based on whether a field value is unique from other values in
214+
the collection. You can use the ``scope`` option to specify one or more
215+
field names that {+odm+} uses to limit the uniqueness check.
216+
217+
This example defines a uniqueness validation rule on the
218+
``Person`` model to ensure that the ``first_name`` field value is
219+
unique within documents that have the same ``last_name`` value:
220+
221+
.. literalinclude:: /includes/data-modeling/validation.rb
222+
:start-after: start-unique
223+
:end-before: end-unique
224+
:language: ruby
225+
:emphasize-lines: 7
226+
:dedent:
227+
228+
.. tip:: Alternative Helper Method
229+
230+
The ``Mongoid::Document`` module provides macro methods for certain
231+
validations. Instead of using the ``uniqueness`` validation helper in the
232+
``validates`` macro statement, you can use the
233+
``validates_uniqueness_of`` method, as shown in the following code:
234+
235+
.. code-block:: ruby
236+
237+
validates_uniqueness_of :first_name
238+
239+
{+odm+} uses a ``primary`` read preference when you use the
240+
``validates_uniqueness_of`` method on a model, because if it
241+
queries a secondary member of the replica set, it might read stale data.
242+
243+
This method takes a ``conditions`` option that allows you to specify
244+
conditions to add when {+odm+} checks for uniqueness:
245+
246+
.. code-block:: ruby
247+
248+
validates_uniqueness_of :name, conditions: -> { where(:age.gte => 10) }
249+
250+
.. _mongoid-association-validation:
251+
252+
Validate Associations
253+
~~~~~~~~~~~~~~~~~~~~~
254+
255+
You can use the ``validates_associated`` helper to validate any
256+
associations that your model has. When you include this validation rule,
257+
{+odm+} validates any association documents any time you try to
258+
save an instance.
259+
260+
.. TODO link to associations page
261+
262+
This example defines an association validation rule on the
263+
``Author`` model to run the validation rules for the embedded ``Book``
264+
instances:
265+
266+
.. literalinclude:: /includes/data-modeling/validation.rb
267+
:start-after: start-assoc
268+
:end-before: end-assoc
269+
:language: ruby
270+
:emphasize-lines: 6
271+
:dedent:
272+
273+
.. important::
274+
275+
Don't use the ``validates_associated`` helper on both ends of your
276+
associations because this causes {+odm+} to perform validations in an
277+
infinite loop.
278+
279+
.. _mongoid-other-validation:
280+
281+
Custom Validation Rules
282+
~~~~~~~~~~~~~~~~~~~~~~~
283+
284+
You can use the ``validates_each`` and ``validates_with`` helpers to
285+
create custom validators. To learn more about these helpers and view
286+
examples, see the `validates_each
287+
<https://guides.rubyonrails.org/active_record_validations.html#validates-each>`__
288+
and `validates_with
289+
<https://guides.rubyonrails.org/active_record_validations.html#validates-with>`__
290+
references in the Active Record documentation.
291+
292+
To learn more about custom validators, see `Performing Custom
293+
Validations
294+
<https://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations>`__
295+
in the Active Record documentation.
296+
297+
Behavior
298+
--------
299+
300+
{+odm+} performs validation when you persist, or save, a document to the
301+
database. The following methods trigger your validation rules, so
302+
{+odm+} saves the object to the database only if it passes validation:
303+
304+
- ``create()``
305+
- ``save()``
306+
- ``update()``
307+
308+
When you use the ``-!`` suffixed version of the preceding methods,
309+
{+odm+} returns an ``Mongoid::Errors::Validations`` exception if
310+
validation fails for an object.
311+
312+
Trigger Validation
313+
~~~~~~~~~~~~~~~~~~
314+
315+
You can run validations manually by using the ``valid?()`` method. This
316+
method returns ``true`` if the object passes validation, and
317+
``false`` otherwise:
318+
319+
.. literalinclude:: /includes/data-modeling/validation.rb
320+
:start-after: start-valid
321+
:end-before: end-valid
322+
:language: ruby
323+
:emphasize-lines: 7, 11, 14
324+
:dedent:
325+
326+
{+odm+} behaves differently from Active Record when running ``valid?()``
327+
on persisted data. Active Record's ``valid?()`` runs all
328+
validations, but {+odm+}'s ``valid?()`` runs validations only on
329+
documents that are in memory to optimize performance.
330+
331+
Additional Information
332+
----------------------
333+
334+
To learn more about validation methods and macros in {+odm+}, see the
335+
:mongoid-api:`Mongoid::Validatable <Mongoid/Validatable.html>` module
336+
reference in the API documentation.
337+
338+
To view a full list of validations helpers in Active Record, see the
339+
`ActiveModel::Validations::HelperMethods
340+
<https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html>`__
341+
reference in the Rails API documentation.
342+
343+
.. TODO link to field types guide.

0 commit comments

Comments
 (0)