Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-2400

Multiple save calls with accepts_nested_attributes_for

    • Type: Icon: Task Task
    • Resolution: Done
    • 3.0.10
    • Affects Version/s: None
    • Component/s: None
    • None

      Hi,

      I know autosave is automatically enabled when using accepts_nested_attributes_for, but I understand that parent should be saved only once all nested attributes have been updated.

      What I see in my app is the following : parent save is called multiple times for every single nested attribute present in the params hash, being created/updated/destroyed ot not.

      Here is an example with this setup : Node has_many :addresses (+ accepts_nested_attributes_for) :

      I have overloaded Node's save method to trace how many times it is called :

      Unable to find source-code formatter for language: `ruby. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
          def save *args
            @save_calls ||= 0
            @save_calls += 1
            puts "**** SAVE #{@save_calls}"
            super *args
          end
      

      `

      Here I have one address (not created/updated/destroyed : I just submit the form as is) :

      Unable to find source-code formatter for language: `ruby. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      node: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
        name: Serveur 1
        gateway: ''
        addresses_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
          '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
            address: 1.2.3.4
            description: ''
            nat: ''
      

      `

      My log :

      Unable to find source-code formatter for language: `. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      **** SAVE 1
      **** SAVE 2
      **** SAVE 3
      

      `

      Then I add a second address :

      Unable to find source-code formatter for language: `ruby. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      node: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
        name: Serveur 1
        gateway: ''
        addresses_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
          '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
            address: 1.2.3.4
            description: ''
            nat: ''
          '1348502159722': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
            address: 2.3.4.5
            description: ''
            nat: ''
      

      `

      Gives :

      Unable to find source-code formatter for language: `. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      **** SAVE 1
      **** SAVE 2
      **** SAVE 3
      **** SAVE 4
      

      `

      Finally, I return to the form (now with 2 addresses) and resubmit it without changing anything :

      Unable to find source-code formatter for language: `ruby. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      node: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
        name: Serveur 1
        gateway: ''
        addresses_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
          '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
            address: 1.2.3.4
            description: ''
            nat: ''
          '1': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
            address: 2.3.4.5
            description: ''
            nat: ''
      

      `

      Unable to find source-code formatter for language: `. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      **** SAVE 1
      **** SAVE 2
      **** SAVE 3
      **** SAVE 4
      **** SAVE 5
      **** SAVE 6
      

      `

      Node's save is called once for each new address and 3 times for existing one. Of course, and this is the problem, all validators are called too, generating lots of MOPED queries (I removed MOPED log for clarity but there are many queries on each save call.

      Knowing that I normally have many other nested attributes than addresses into Node, it results in a very dirty mongodb usage.

      Note that this only occurs with has_many relations, and not with embedded_in, which is normal since there is no need of autosave.

      So my questions are the following :

      • Is it normal that paren'ts save is called for every nested record ?
      • 1 to 3 times for each ?
      • Even if nothing is modified in parent's or nested attributes ?

      I'm using Mongoid 3.0.6

      Thanks,

            Assignee:
            Unassigned Unassigned
            Reporter:
            gauthier-delacroix gauthier-delacroix
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: