From ee49b9ba197087ee6d13c4e459502e6e1e2256a0 Mon Sep 17 00:00:00 2001 From: rustagir Date: Mon, 25 Nov 2024 17:15:32 -0500 Subject: [PATCH 1/4] DOCSP-45363: validation --- snooty.toml | 1 + source/data-modeling.txt | 4 + source/data-modeling/validation.txt | 340 ++++++++++++++++++++ source/includes/data-modeling/validation.rb | 89 +++++ 4 files changed, 434 insertions(+) create mode 100644 source/data-modeling/validation.txt create mode 100644 source/includes/data-modeling/validation.rb diff --git a/snooty.toml b/snooty.toml index b4c9f5f9..789f516a 100644 --- a/snooty.toml +++ b/snooty.toml @@ -17,6 +17,7 @@ toc_landing_pages = [ [constants] rails-6-version = 6.0 rails-7-version = 7.1 +rails-8-version-docs = "v8.0" odm = "Mongoid" version = "9.0" full-version = "{+version+}.2" diff --git a/source/data-modeling.txt b/source/data-modeling.txt index 8c5d324c..9c39c2e6 100644 --- a/source/data-modeling.txt +++ b/source/data-modeling.txt @@ -17,6 +17,7 @@ Model Your Data Documents Inheritance Nested Attributes + Document Validation In this section, you can learn how to model data in {+odm+}. @@ -28,3 +29,6 @@ In this section, you can learn how to model data in {+odm+}. - :ref:`mongoid-modeling-nested-attr`: Learn how to modify documents and their associations in a single operation. + +- :ref:`mongoid-modeling-validation`: Learn how to create document + validation rules for your model classes. diff --git a/source/data-modeling/validation.txt b/source/data-modeling/validation.txt new file mode 100644 index 00000000..cdb95126 --- /dev/null +++ b/source/data-modeling/validation.txt @@ -0,0 +1,340 @@ +.. _mongoid-modeling-validation: + +=================== +Document Validation +=================== + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: ruby framework, odm, relationship, code example, polymorphic + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +Overview +-------- + +In this guide, you can learn how to define **validation rules** in your +{+odm+} models. After you implement validation into your models, {+odm+} +prevents you from running write operations that violate the validation +rules. Use document validation to restrict data types and value ranges +of document fields in your collections. + +{+odm+} includes ``ActiveModel::Validations`` from Active Record to +provide validation functionality, including an associated and uniqueness +validator. To learn more, see the `Active Record Validations +`__ +Rails guide and `ActiveModel::Validations +`__ +Rails API documentation. + +.. note:: Comparing {+odm+} and MongoDB Validation + + Validation in {+odm+} applies only in the context of your + application and differs from creating schema validation rules in + MongoDB. This means that your validation rules do not apply to write + operations that are performed outside of your application. To learn + more about MongoDB schema validation, see :manual:`Schema Validation + ` in the {+server-manual+}. + +Validation Helpers +------------------ + +{+odm+} supports Active Record validation helpers that you can use when defining your +model classes. You can use these helpers to set common validation rules +in your application, such as checking for the presence of a field, +comparing a field value to a specified value, or ensuring that a field +has a unique value. + +Define a Validation Rule +~~~~~~~~~~~~~~~~~~~~~~~~ + +Use the ``validates`` macro to create a validation rule, then include +the validation helper and the required specifications for the rule. + +.. tip:: + + Each validation helper accepts one or more field names, which allows you + to define the same rule for multiple fields. + +The following code demonstrates how to use the ``presence`` validation +helper to require that ``Person`` instances contain a value for the +``name`` field: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-simple-val + :end-before: end-simple-val + :language: ruby + :emphasize-lines: 5 + :dedent: + +You can learn about other useful validation helpers in the +:ref:`mongoid-common-validations` section of this guide. + +.. _mongoid-common-validations: + +Common Validations +------------------ + +In this section, you can learn the following common validation rules and view +examples that use the appropriate validation helper: + +- :ref:`mongoid-compare-validation` +- :ref:`mongoid-format-validation` +- :ref:`mongoid-inclusion-exclusion-validation` +- :ref:`mongoid-presence-absence-validation` +- :ref:`mongoid-uniqueness-validation` +- :ref:`mongoid-association-validation` +- :ref:`mongoid-other-validation` + +.. _mongoid-compare-validation: + +Comparison Rule +~~~~~~~~~~~~~~~ + +You can use the ``comparison`` helper to validate a document based on +the value of a specified field. + +The ``comparison`` helper supports the following options: + +- ``greater_than``: The value must be greater than the supplied value. +- ``greater_than_or_equal_to``: The value must be greater than or equal to the supplied value. +- ``equal_to``: The value must be equal to the supplied value. +- ``less_than``: The value must be less than the supplied value. +- ``less_than_or_equal_to``: The value must be less than or equal to the supplied value. +- ``other_than``: The value must be different than the supplied value. + +This example defines the following comparison validation rules on the +``Order`` model: + +- ``delivery_date``: Must be after (greater than) the value of ``order_date`` +- ``quantity``: Must be less than ``5`` + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-comparison + :end-before: end-comparison + :language: ruby + :emphasize-lines: 8-9 + :dedent: + +.. _mongoid-format-validation: + +Formatting Rule +~~~~~~~~~~~~~~~ + +You can use the ``format`` helper to validate a document based on +whether a field value matches a regular expression. Specify the regular +expression to the ``with`` option. + +This example defines a format validation rule on the +``User`` model to ensure that the ``username`` field contains only +letters: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-fmt + :end-before: end-fmt + :language: ruby + :emphasize-lines: 6 + :dedent: + +.. tip:: Alternative Helper Method + + The ``Mongoid::Document`` module provides macro methods for certain + validations. Instead of using the ``format`` validation helper in the + ``validates`` macro statement, you can use the + ``validates_format_of`` method, as shown in the following code: + + .. code-block:: ruby + + validates_format_of :username, with: /\A[a-zA-Z]+\z/ + +.. _mongoid-inclusion-exclusion-validation: + +Inclusion or Exclusion Rule +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can use the ``inclusion`` and ``exclusion`` helpers to validate a +document based on whether a field value is in or not in a specified list +of values. Specify the list to the ``in`` option. + +This example defines an inclusion validation rule on the +``Order`` model to ensure that the ``shipping`` field value is one of +the accepted values: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-inclusion + :end-before: end-inclusion + :language: ruby + :emphasize-lines: 6 + :dedent: + +.. _mongoid-presence-absence-validation: + +Presence or Absence Rule +~~~~~~~~~~~~~~~~~~~~~~~~ + +You can use the ``presence`` and ``absence`` helpers to validate a +document based on whether a field value is present or absent (empty). + +This example defines an absence validation rule on the +``Order`` model to ensure that the ``delivery_date`` field value is +either ``nil`` or an empty string: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-absence + :end-before: end-absence + :language: ruby + :emphasize-lines: 6 + :dedent: + +.. tip:: Alternative Helper Method + + The ``Mongoid::Document`` module provides macro methods for certain + validations. Instead of using the ``presence`` validation helper in the + ``validates`` macro statement, you can use the + ``validates_presence_of`` method, as shown in the following code: + + .. code-block:: ruby + + validates_presence_of :delivery_date + +.. _mongoid-uniqueness-validation: + +Uniqueness Rule +~~~~~~~~~~~~~~~ + +You can use the ``uniqueness`` helper to validate a +document based on whether a field value is unique from other values in +the collection. You can use the ``scope`` option to specify one or more +field names that {+odm+} uses to limit the uniqueness check. + +This example defines a uniqueness validation rule on the +``Person`` model to ensure that the ``first_name`` field value is +unique within documents that have the same ``last_name`` value: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-unique + :end-before: end-unique + :language: ruby + :emphasize-lines: 7 + :dedent: + +.. tip:: Alternative Helper Method + + The ``Mongoid::Document`` module provides macro methods for certain + validations. Instead of using the ``uniqueness`` validation helper in the + ``validates`` macro statement, you can use the + ``validates_uniqueness_of`` method, as shown in the following code: + + .. code-block:: ruby + + validates_uniqueness_of :first_name + + {+odm+} uses a ``primary`` read preference when you use the + ``validates_uniqueness_of`` method on a model, because if it + queries a secondary member of the replica set, there is a possibility + that it is reading stale data. + + This method takes a ``conditions`` option that allows you to specify + condition to add when {+odm+} checks for uniqueness: + + .. code-block:: ruby + + validates_uniqueness_of :name, conditions: -> { where(:age.gte => 10) } + +.. _mongoid-association-validation: + +Validate Associations +~~~~~~~~~~~~~~~~~~~~~ + +You can use the ``validates_associated`` helper to validate any +associations that your model has. When you include this validation rule, +{+odm+} validates any association documents any time you try to +save an instance. + +.. TODO link to associations page + +This example defines an association validation rule on the +``Author`` model to run the validation rules for the embedded ``Book`` +instances: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-assoc + :end-before: end-assoc + :language: ruby + :emphasize-lines: 6 + :dedent: + +.. important:: + + Don't use the ``validates_associated`` helper on both ends of your + associations, as this causes {+odm+} to perform validations in an + infinite loop. + +.. _mongoid-other-validation: + +Custom Validation Rules +~~~~~~~~~~~~~~~~~~~~~~~ + +You can use the ``validates_each`` and ``validates_with`` helpers to +create custom validators. To learn more about these helpers and view +examples, see the `validates_each +`__ +and `validates_with +`__ +references in the Active Record documentation. + +To learn more about custom validators, see `Performing Custom +Validations +`__ +in the Active Record documentation. + +Behavior +-------- + +{+odm+} performs validation when you persist, or save, a document to the +database. The following methods trigger your validation rules, so +{+odm+} saves the object to the database only if it passes validation: + +- ``create()`` +- ``save()`` +- ``update()`` + +When you use the ``-!`` suffixed version of the preceding methods, +{+odm+} returns an ``Mongoid::Errors::Validations`` exception if +validation fails for an object. + +You can run validations manually by using the ``valid?()`` method.This +method returns ``true`` if the object passes validation, and +``false`` otherwise: + +.. literalinclude:: /includes/data-modeling/validation.rb + :start-after: start-valid + :end-before: end-valid + :language: ruby + :dedent: + +{+odm+} behaves differently to Active Record when running ``valid?()`` +on persisted data. Active Record's ``valid?()`` runs all +validations, but {+odm+}'s ``valid?()`` runs validations only on +documents that are in memory as an optimization. + +Additional Information +---------------------- + +To learn more about validation methods and macros in {+odm+}, see the +:mongoid-api:`Mongoid::Validatable ` module +reference in the API documentation. + +To view a full list of validations helpers in Active Record, see the +`ActiveModel::Validations::HelperMethods +`__ +reference in the Rails API documentation. + +.. TODO link to field types guide. diff --git a/source/includes/data-modeling/validation.rb b/source/includes/data-modeling/validation.rb new file mode 100644 index 00000000..47b51e27 --- /dev/null +++ b/source/includes/data-modeling/validation.rb @@ -0,0 +1,89 @@ +# start-simple-val +class Person + include Mongoid::Document + + field :name, type: String + validates :name, presence: true +end +# end-simple-val + +# start-comparison +class Order + include Mongoid::Document + + field :order_date, type: DateTime + field :delivery_date, type: DateTime + field :quantity, type: Integer + + validates :delivery_date, comparison: { greater_than: :order_date } + validates :quantity, comparison: { less_than: 5 } +end +# end-comparison + +# start-fmt +class User + include Mongoid::Document + + field :username, type: String + + validates :username, format: { with: /\A[a-zA-Z]+\z/ } +end +# end-fmt + +# start-inclusion +class Order + include Mongoid::Document + + field :shipping, type: String + + validates :shipping, inclusion: { in: %w(standard priority overnight) } +end +# end-inclusion + +# start-absence +class Order + include Mongoid::Document + + field :delivery_date, type: String + + validates :delivery_date, absence: true +end +# end-absence + +# start-unique +class Person + include Mongoid::Document + + field :first_name, type: String + field :last_name, type: String + + validates :first_name, uniqueness: { scope: :last_name } +end +# end-unique + +# start-assoc +class Author + include Mongoid::Document + + embeds_many :books + + validates_associated :books +end +# end-assoc + +# start-valid +class Person + include Mongoid::Document + + field :name, type: String + field :age, type: Integer + + validates :age, comparison: { greater_than_or_equal_to: 0 } +end + +# Returns true +Person.new(name: "Berta Odom", age: 4).valid? + +# Returns false +Person.new(name: "Cody Peng", age: -5).valid? +# end-valid \ No newline at end of file From d1b9da3ddab5d268c93af5f27c892e40fcf95473 Mon Sep 17 00:00:00 2001 From: rustagir Date: Mon, 25 Nov 2024 17:16:20 -0500 Subject: [PATCH 2/4] keywords --- source/data-modeling/validation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/data-modeling/validation.txt b/source/data-modeling/validation.txt index cdb95126..de6ba6c5 100644 --- a/source/data-modeling/validation.txt +++ b/source/data-modeling/validation.txt @@ -9,7 +9,7 @@ Document Validation :values: reference .. meta:: - :keywords: ruby framework, odm, relationship, code example, polymorphic + :keywords: ruby framework, odm, schema, code example .. contents:: On this page :local: From dc8e6a188d0efebfd0edb4d52a5bd82dffbe302e Mon Sep 17 00:00:00 2001 From: rustagir Date: Mon, 25 Nov 2024 17:24:56 -0500 Subject: [PATCH 3/4] wip --- source/data-modeling/validation.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/data-modeling/validation.txt b/source/data-modeling/validation.txt index de6ba6c5..133aa958 100644 --- a/source/data-modeling/validation.txt +++ b/source/data-modeling/validation.txt @@ -82,8 +82,8 @@ You can learn about other useful validation helpers in the Common Validations ------------------ -In this section, you can learn the following common validation rules and view -examples that use the appropriate validation helper: +In this section, you can learn about the following common validation +rules and view examples that use validation helpers: - :ref:`mongoid-compare-validation` - :ref:`mongoid-format-validation` @@ -310,6 +310,9 @@ When you use the ``-!`` suffixed version of the preceding methods, {+odm+} returns an ``Mongoid::Errors::Validations`` exception if validation fails for an object. +Trigger Validation +~~~~~~~~~~~~~~~~~~ + You can run validations manually by using the ``valid?()`` method.This method returns ``true`` if the object passes validation, and ``false`` otherwise: @@ -318,6 +321,7 @@ method returns ``true`` if the object passes validation, and :start-after: start-valid :end-before: end-valid :language: ruby + :emphasize-lines: 7, 11, 14 :dedent: {+odm+} behaves differently to Active Record when running ``valid?()`` @@ -329,7 +333,7 @@ Additional Information ---------------------- To learn more about validation methods and macros in {+odm+}, see the -:mongoid-api:`Mongoid::Validatable ` module +:mongoid-api:`Mongoid::Validatable ` module reference in the API documentation. To view a full list of validations helpers in Active Record, see the From 543bc1cc149e84219215edcd2609e99fe555cebc Mon Sep 17 00:00:00 2001 From: rustagir Date: Mon, 2 Dec 2024 09:28:50 -0500 Subject: [PATCH 4/4] SA PR fixes 1 --- source/data-modeling.txt | 4 ---- source/data-modeling/validation.txt | 21 +++++++++---------- source/interact-data.txt | 6 +++++- .../nested-attributes.txt | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) rename source/{data-modeling => interact-data}/nested-attributes.txt (99%) diff --git a/source/data-modeling.txt b/source/data-modeling.txt index 9c39c2e6..bfd1c377 100644 --- a/source/data-modeling.txt +++ b/source/data-modeling.txt @@ -16,7 +16,6 @@ Model Your Data Documents Inheritance - Nested Attributes Document Validation In this section, you can learn how to model data in {+odm+}. @@ -27,8 +26,5 @@ In this section, you can learn how to model data in {+odm+}. - :ref:`mongoid-modeling-inheritance`: Learn how to implement inheritance in your model classes. -- :ref:`mongoid-modeling-nested-attr`: Learn how to modify documents and - their associations in a single operation. - - :ref:`mongoid-modeling-validation`: Learn how to create document validation rules for your model classes. diff --git a/source/data-modeling/validation.txt b/source/data-modeling/validation.txt index 133aa958..9f96c72f 100644 --- a/source/data-modeling/validation.txt +++ b/source/data-modeling/validation.txt @@ -129,8 +129,8 @@ Formatting Rule ~~~~~~~~~~~~~~~ You can use the ``format`` helper to validate a document based on -whether a field value matches a regular expression. Specify the regular -expression to the ``with`` option. +whether a field value matches a regular expression. Use the ``with`` +option to specify the regular expression. This example defines a format validation rule on the ``User`` model to ensure that the ``username`` field contains only @@ -160,8 +160,8 @@ Inclusion or Exclusion Rule ~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can use the ``inclusion`` and ``exclusion`` helpers to validate a -document based on whether a field value is in or not in a specified list -of values. Specify the list to the ``in`` option. +document based on whether a field value is in a specified list +of values. Use the ``in`` option to specify the list of values. This example defines an inclusion validation rule on the ``Order`` model to ensure that the ``shipping`` field value is one of @@ -238,11 +238,10 @@ unique within documents that have the same ``last_name`` value: {+odm+} uses a ``primary`` read preference when you use the ``validates_uniqueness_of`` method on a model, because if it - queries a secondary member of the replica set, there is a possibility - that it is reading stale data. + queries a secondary member of the replica set, it might read stale data. This method takes a ``conditions`` option that allows you to specify - condition to add when {+odm+} checks for uniqueness: + conditions to add when {+odm+} checks for uniqueness: .. code-block:: ruby @@ -274,7 +273,7 @@ instances: .. important:: Don't use the ``validates_associated`` helper on both ends of your - associations, as this causes {+odm+} to perform validations in an + associations because this causes {+odm+} to perform validations in an infinite loop. .. _mongoid-other-validation: @@ -313,7 +312,7 @@ validation fails for an object. Trigger Validation ~~~~~~~~~~~~~~~~~~ -You can run validations manually by using the ``valid?()`` method.This +You can run validations manually by using the ``valid?()`` method. This method returns ``true`` if the object passes validation, and ``false`` otherwise: @@ -324,10 +323,10 @@ method returns ``true`` if the object passes validation, and :emphasize-lines: 7, 11, 14 :dedent: -{+odm+} behaves differently to Active Record when running ``valid?()`` +{+odm+} behaves differently from Active Record when running ``valid?()`` on persisted data. Active Record's ``valid?()`` runs all validations, but {+odm+}'s ``valid?()`` runs validations only on -documents that are in memory as an optimization. +documents that are in memory to optimize performance. Additional Information ---------------------- diff --git a/source/interact-data.txt b/source/interact-data.txt index b11a2b05..2e3e3707 100644 --- a/source/interact-data.txt +++ b/source/interact-data.txt @@ -18,6 +18,7 @@ Interact with Data Modify Query Results Search Text Transactions and Sessions + Nested Attributes In this section, you can learn how to use {+odm+} to interact with your MongoDB data. @@ -32,4 +33,7 @@ MongoDB data. searches on text fields. - :ref:`mongoid-data-txn`: Learn how to perform multi-document - transactions to make atomic data changes. \ No newline at end of file + transactions to make atomic data changes. + +- :ref:`mongoid-data-nested-attr`: Learn how to modify documents and + their associations in a single operation. \ No newline at end of file diff --git a/source/data-modeling/nested-attributes.txt b/source/interact-data/nested-attributes.txt similarity index 99% rename from source/data-modeling/nested-attributes.txt rename to source/interact-data/nested-attributes.txt index 7e8296d2..fcd10dd9 100644 --- a/source/data-modeling/nested-attributes.txt +++ b/source/interact-data/nested-attributes.txt @@ -1,4 +1,4 @@ -.. _mongoid-modeling-nested-attr: +.. _mongoid-data-nested-attr: ================= Nested Attributes