From 378ecd6caebe9ff8aa10854b909df2b6333733f8 Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 22 Nov 2024 09:47:48 -0500 Subject: [PATCH 1/4] DOCSP-45360: nested attributes --- source/data-modeling.txt | 4 + source/data-modeling/nested-attributes.txt | 190 +++++++++++++++++++ source/includes/data-modeling/nested_attr.rb | 60 ++++++ 3 files changed, 254 insertions(+) create mode 100644 source/data-modeling/nested-attributes.txt create mode 100644 source/includes/data-modeling/nested_attr.rb diff --git a/source/data-modeling.txt b/source/data-modeling.txt index 829f6643..8c5d324c 100644 --- a/source/data-modeling.txt +++ b/source/data-modeling.txt @@ -16,6 +16,7 @@ Model Your Data Documents Inheritance + Nested Attributes In this section, you can learn how to model data in {+odm+}. @@ -24,3 +25,6 @@ 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. diff --git a/source/data-modeling/nested-attributes.txt b/source/data-modeling/nested-attributes.txt new file mode 100644 index 00000000..54482f21 --- /dev/null +++ b/source/data-modeling/nested-attributes.txt @@ -0,0 +1,190 @@ +.. _mongoid-modeling-nested-attr: + +================= +Nested Attributes +================= + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: ruby framework, odm, embeddings, code example, queries + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +Overview +-------- + +In this guide, you can learn how to define **nested attributes** on +models to enable data operations on documents and their associations. +After you define a nested attribute, you can specify updates to +top-level and associated documents in a single parameter hash. This might be +useful if your application requires editing multiple documents within a single +form. + +Behavior +-------- + +You can enable nested attributes for any association, embedded or +referenced. To add a nested attribute for an association, provide the +association name to the ``accepts_nested_attributes_for`` macro when +defining a model class. + +The following code defines embedded associations on the ``Band`` model +class and includes the ``accepts_nested_attributes_for`` macro: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-simple-nested + :end-before: end-simple-nested + :language: ruby + :emphasize-lines: 5 + :dedent: + +.. note:: Autosave Enabled + + When you add nested attribute functionality to a referenced + association, {+odm+} automatically enables autosave for that + association. + +When you enable nested attributes behavior on an association, {+odm+} +adds an additional method to the base model. You can use this method to +update the attributes by using this added functionality. + +The method is the association name suffixed with ``_attributes``. For +example, the setter method to update the ``producers`` association is +``producer_attributes``. + +You can use this method directly, or you can use the name of the method +as an attribute in the updates for the top-level class. In this case, +{+odm+} calls the appropriate setter method internally. + +The following code retrieves an instance of ``Band``, then uses the +nested attribute update method ``producer_attributes`` to set a value +for the association document: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-use-method + :end-before: end-use-method + :language: ruby + :emphasize-lines: 4 + :dedent: + +There are multiple ways to update a nested attribute: + +- Use the ``_attributes`` setter method. +- Use the ``attributes`` setter method and specify ``_attributes`` in the value to update the associations. +- Use the ``update_attributes`` setter method and specify the attribute + names in the value to update the associations. +- Use the ``update()`` method and specify ``_attributes`` in the value to update the associations. +- Use the ``create()`` method and specify ``_attributes`` in the value to create the associations. + +The following example demonstrates how to create a ``Band`` instance +with associated ``album`` records in a single statement: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-create-attr + :end-before: end-create-attr + :language: ruby + :emphasize-lines: 3-5 + :dedent: + +Creating Nested Documents +------------------------- + +You can create new nested documents by using the nested attributes +feature. When creating a document, omit the ``_id`` field. The following +code uses the ``update()`` method to create a nested ``album`` document +on an existing ``Band`` instance: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-update-create + :end-before: end-update-create + :language: ruby + :dedent: + +This action appends the new document to the existing set, without changing +any existing nested documents. + +Updating Nested Documents +------------------------- + +You can update existing nested documents by using the nested attributes +feature. To update a nested document, pass the ``_id`` value for the +document to direct {+odm+} to use attributes to update it. The following +example uses the ``_id`` value of an ``albums`` entry to update the +``year`` field: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-update-id + :end-before: end-update-id + :language: ruby + :dedent: + +.. note:: No Matching Document + + If {+odm+} does not match a document that has the specified ``_id`` + value, it raises a ``Mongoid::Errors::DocumentNotFound`` exception. + +Delete Nested Documents +----------------------- + +You can delete nested documents by specifying the ``_destroy`` +attribute to the ``update()`` method. To enable deletion of nested +document, you must set ``allow_destroy: true`` in the +``accepts_nested_attributes_for`` declaration, as shown in the following +code: + +.. code-block:: ruby + :emphasize-lines: 3 + + class Band + # ... + accepts_nested_attributes_for :albums, allow_destroy: true + end + +The following code uses the ``_destroy`` attribute to delete the first +``albums`` entry of a ``Band`` instance: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-delete-id + :end-before: end-delete-id + :language: ruby + :emphasize-lines: 6 + :dedent: + +.. note:: No Matching Document + + If {+odm+} does not match a document that has the specified ``_id`` + value, it raises a ``Mongoid::Errors::DocumentNotFound`` exception. + +Combine Operations on Nested Documents +-------------------------------------- + +You can perform multiple data operations on nested documents by using +the nested attributes feature. + +The following code creates a nested document, updates an existing +document, and destroys a document in the same ``Band`` instance: + +.. literalinclude:: /includes/data-modeling/nested_attr.rb + :start-after: start-multiple-ops + :end-before: end-multiple-ops + :language: ruby + :dedent: + +Additional Information +---------------------- + +To learn more about querying, see :ref:`mongoid-data-specify-query`. + +.. TODO link to CRUD guide + +.. TODO link to associations guide \ No newline at end of file diff --git a/source/includes/data-modeling/nested_attr.rb b/source/includes/data-modeling/nested_attr.rb new file mode 100644 index 00000000..f53a979d --- /dev/null +++ b/source/includes/data-modeling/nested_attr.rb @@ -0,0 +1,60 @@ +# start-simple-nested +class Band + include Mongoid::Document + embeds_many :albums + belongs_to :producer + accepts_nested_attributes_for :albums, :producer +end +# end-simple-nested + +#start-use-method +# Retrieves a Band instance +band = Band.where(name: 'Tennis').first + +# Updates the "producer" association +band.producer_attributes = { name: 'Alaina Moore' } +#end-use-method + +# start-create-attr +band = Band.create( + name: 'Tennis', + albums_attributes: [ + { name: 'Swimmer', year: 2020 }, + { name: 'Young & Old', year: 2013 }, + ] +) +# end-create-attr + +# start-update-create +band = Band.where(name: 'Vampire Weekend').first +band.update(albums_attributes: [ + { name: 'Contra', year: 2010 } +]) +# end-update-create + +# start-update-id +band = Band.where(name: 'Vampire Weekend').first +# Retrieves the first entry from the albums array +album = band.albums.first +# Updates the entry by passing the _id value +band.update(albums_attributes: [ + { _id: album._id, year: 2011 } ]) +# end-update-id + +# start-delete-id +band = Band.where(name: 'Vampire Weekend').first +# Retrieves the first entry from the albums array +album = band.albums.first +# Deletes the entry by passing the _id value +band.update(albums_attributes: [ + { _id: album._id, _destroy: true } ]) +# end-delete-id + +# start-multiple-ops +band = Band.where(name: 'Yeah Yeah Yeahs').first +# Performs multiple data changes +band.update(albums_attributes: [ + { name: 'Show Your Bones', year: 2006 }, + { _id: 1, name: 'Fever To T3ll' }, + { _id: 2, _destroy: true } ]) +# end-multiple-ops \ No newline at end of file From e0c4aa3ce183f942e53d9824657fc17dc1bcfe93 Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 22 Nov 2024 09:53:34 -0500 Subject: [PATCH 2/4] vale + fixes --- source/data-modeling/nested-attributes.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/data-modeling/nested-attributes.txt b/source/data-modeling/nested-attributes.txt index 54482f21..f22ff6f6 100644 --- a/source/data-modeling/nested-attributes.txt +++ b/source/data-modeling/nested-attributes.txt @@ -52,10 +52,10 @@ class and includes the ``accepts_nested_attributes_for`` macro: association. When you enable nested attributes behavior on an association, {+odm+} -adds an additional method to the base model. You can use this method to +adds a special method to the base model. You can use this method to update the attributes by using this added functionality. -The method is the association name suffixed with ``_attributes``. For +The method name is the association name suffixed with ``_attributes``. For example, the setter method to update the ``producers`` association is ``producer_attributes``. @@ -172,7 +172,8 @@ You can perform multiple data operations on nested documents by using the nested attributes feature. The following code creates a nested document, updates an existing -document, and destroys a document in the same ``Band`` instance: +document, and deletes a document in the ``albums`` array of a ``Band`` +instance: .. literalinclude:: /includes/data-modeling/nested_attr.rb :start-after: start-multiple-ops From 2db9c4d115f3593f8bc2eba87ac18c0410df1a75 Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 22 Nov 2024 09:54:45 -0500 Subject: [PATCH 3/4] fixes --- source/includes/data-modeling/nested_attr.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/includes/data-modeling/nested_attr.rb b/source/includes/data-modeling/nested_attr.rb index f53a979d..e81a4c4d 100644 --- a/source/includes/data-modeling/nested_attr.rb +++ b/source/includes/data-modeling/nested_attr.rb @@ -10,7 +10,6 @@ class Band #start-use-method # Retrieves a Band instance band = Band.where(name: 'Tennis').first - # Updates the "producer" association band.producer_attributes = { name: 'Alaina Moore' } #end-use-method @@ -20,8 +19,7 @@ class Band name: 'Tennis', albums_attributes: [ { name: 'Swimmer', year: 2020 }, - { name: 'Young & Old', year: 2013 }, - ] + { name: 'Young & Old', year: 2013 }] ) # end-create-attr From c176d8b5e1709bb56922f12af379e951fe2ba03f Mon Sep 17 00:00:00 2001 From: rustagir Date: Fri, 22 Nov 2024 12:35:28 -0500 Subject: [PATCH 4/4] NR PR fixes 1 --- source/data-modeling/nested-attributes.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/source/data-modeling/nested-attributes.txt b/source/data-modeling/nested-attributes.txt index f22ff6f6..7e8296d2 100644 --- a/source/data-modeling/nested-attributes.txt +++ b/source/data-modeling/nested-attributes.txt @@ -53,7 +53,7 @@ class and includes the ``accepts_nested_attributes_for`` macro: When you enable nested attributes behavior on an association, {+odm+} adds a special method to the base model. You can use this method to -update the attributes by using this added functionality. +update the attributes. The method name is the association name suffixed with ``_attributes``. For example, the setter method to update the ``producers`` association is @@ -110,17 +110,17 @@ on an existing ``Band`` instance: :language: ruby :dedent: -This action appends the new document to the existing set, without changing +This action appends the new document to the existing set without changing any existing nested documents. Updating Nested Documents ------------------------- You can update existing nested documents by using the nested attributes -feature. To update a nested document, pass the ``_id`` value for the -document to direct {+odm+} to use attributes to update it. The following -example uses the ``_id`` value of an ``albums`` entry to update the -``year`` field: +feature. To instruct {+odm+} to update a nested document by using +attributes, pass the document's ``_id`` value to the ``update()`` +method. The following example uses the ``_id`` value of an ``albums`` +entry to update the ``year`` field: .. literalinclude:: /includes/data-modeling/nested_attr.rb :start-after: start-update-id @@ -128,7 +128,7 @@ example uses the ``_id`` value of an ``albums`` entry to update the :language: ruby :dedent: -.. note:: No Matching Document +.. important:: No Matching Document If {+odm+} does not match a document that has the specified ``_id`` value, it raises a ``Mongoid::Errors::DocumentNotFound`` exception. @@ -160,7 +160,7 @@ The following code uses the ``_destroy`` attribute to delete the first :emphasize-lines: 6 :dedent: -.. note:: No Matching Document +.. important:: No Matching Document If {+odm+} does not match a document that has the specified ``_id`` value, it raises a ``Mongoid::Errors::DocumentNotFound`` exception. @@ -184,8 +184,9 @@ instance: Additional Information ---------------------- -To learn more about querying, see :ref:`mongoid-data-specify-query`. +To learn more about querying, see the :ref:`mongoid-data-specify-query` +guide. .. TODO link to CRUD guide -.. TODO link to associations guide \ No newline at end of file +.. TODO link to associations guide