Delayed atomic updates from new embedded children can be written to incorrect paths

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • None
    • Ruby Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Summary:

      When a persisted document receives a new `embeds_one` child and its nested `embeds_many` association in one `attributes=` call, the nested data can be written to the wrong path.

      Description:

      The new embedded child is created before it is attached to its parent. If the child contains an `embeds_many` association, assigning that association records a delayed atomic set relative to the child. When the root document is saved, that delayed set can be included in the root update without the child path.

      With different stored names, the nested array can appear as an unintended field on the root document. With the same stored name, it can be merged into the root array or cause a MongoDB path conflict.

      Root cause:

      `EmbedsOne::Buildable#build` creates the child without parent or association metadata. The child therefore cannot calculate a path from the root document. The `embeds_many` batch path already supplies that metadata and clears delayed sets for newly collected children.

      Reproduction:

      • Define a persisted root document with an `embeds_one` association.
      • Define the embedded child with an `embeds_many` association.
      • Assign the root and the new child in one `attributes=` call.
      • Include nested `embeds_many` attributes in the new child.
      • Save the root document.

      The same problem can be exercised through `accepts_nested_attributes_for`. It occurs with both different stored names and the same stored name. Updating the nested association on an already persisted child does not reproduce the issue.

      Expected result:

      The nested association is stored only inside the new `embeds_one` child. The root document has no unintended field, and saving does not produce a conflicting modification error.

      Actual result:

      The nested association can be written at the root level, merged into a root association with the same stored name, or cause a conflicting modification error.

      Affected version:

      The issue was reproduced against Mongoid 9.0.9 and the master branch before the change.

      Related tickets:

      • MONGOID-5747 covers a related incorrect atomic update for embedded associations, but does not seem to be the same issue.
      • MONGOID-2989 is an older, closed ticket about conflicting modifications with nested attributes.

            Assignee:
            Unassigned
            Reporter:
            Tatsuhiro Ujihisa (EXT)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: