Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

accepts_nested_attributes_for does't work when nested_attributes hash has an :id entry

#2415

When a parent accepts_nested_attributes_for :chilld and you call parent.update_attributes(hash) if the hash has an :id entry in the child_attributes subhash then the update_attributes call with return true without updating the associated object, this happens regardless of if the rest of the data in the subhash is valid or not, here is an example.

order = Order.first
=> #<Order id: 1, client_id: 1, amount: 123, created_at: "2009-04-03 23:09:03", updated_at: "2009-04-03 23:09:03">
attrs = {:client_attributes => {:state => "ASDASDADAD", :id => 12931204}}
=> {:client_attributes=>{:state=>"ASDASDADAD", :id=>12931204}}
order.client
=> #<Client id: 1, name: "blad", state: "NY", created_at: "2009-04-03 23:07:50", updated_at: "2009-04-03 23:07:50">
order.update_attributes(attrs)
=> true
order.client
=> #<Client id: 1, name: "blad", state: "NY", created_at: "2009-04-03 23:07:50", updated_at: "2009-04-03 23:07:50">
attrs = {:client_attributes => {:state => "ASDASDADAD"}}
=> {:client_attributes=>{:state=>"ASDASDADAD"}}
order.update_attributes(attrs)
=> false
order.client
=> #<Client id: nil, name: nil, state: "ASDASDADAD", created_at: nil, updated_at: nil>
order.errors.full_messages
=> ["Client state is not included in the list"]

Reported by vlad (at breyter) · April 4th, 2009 @ 07:12 AM

State: wontfix
Milestone: 3.0.2
Assigned to: José Valim José Valim
Importance: none

Activity

  1. Eloy Duran
    Eloy Duran
    • Assigned user set to Eloy Duran
    • Milestone changed from 2.x to 2.3.6

    December 30th, 2009 @ 07:55 PM

  2. Eloy Duran
    Eloy Duran
    • State changed from new to verified

    January 7th, 2010 @ 04:24 PM

  3. Repository
    Repository
    • State changed from verified to resolved

    (from [9550916903c931161f04a98091fba712d7fa5c1d]) Raise a RecordNotFound if an ID in nested attributes is given but doesn't return a record. [#2415 state:resolved] http://github.com/rails/rails/commit/9550916903c931161f04a98091fba7...

    January 7th, 2010 @ 07:15 PM

  4. Repository
    Repository

    (from [0dbe0f670e08e6adfedc395dadb9859ca2df6d4b]) Raise a RecordNotFound if an ID in nested attributes is given but doesn't return a record. [#2415 state:resolved] http://github.com/rails/rails/commit/0dbe0f670e08e6adfedc395dadb985...

    January 7th, 2010 @ 07:32 PM

  5. Scott Rushforth
    Scott Rushforth

    This patch does help clarify what is going on, but does not solve the issue when creating a new object.

    For example:

    Order model:

    class Order < ActiveRecord::Base
    belongs_to :customer accepts_nested_attributes_for :customer end

    Parameters:

    {"action"=>"create", "authenticity_token"=>"ZXdeEAgTsQFIihAFgVBaTsf9GR6o/cuCNmphc4OaMzU=", "order"=>{ "customer_attributes"=>{"company"=>"TestCompany", "phone_alt"=>"555-555-8251", "id"=>"101", "last_name"=>"Jones", "phone"=>"", "fax"=>"555-222-3333", "first_name"=>"Bob", "email"=>"bob@notreal.com"}, "invoice_comments"=>"", "customer_id"=>"101"} }

    Results in:

    ActiveRecord::RecordNotFound (Couldn't find Customer with ID=101 for Order with ID=):

    To further explain, the use-case-scenario of this is that I am building a system where there will be an order form, and in this order form there is a nested form for a customer. The goals of the application are to both allow the user to create a new order, and simultaneously associate this new order with a given customer (in this case customer id 101) and also if they choose update the customers information at the same time. (IE - the customer has made orders in the past, but calls in to make a new order today, and also gives a new phone number. no need to go back to another form to update the phone number when you should just be able to do it from the order form.)

    For fun I have also tried to omit params[:order][:customer_id] = 101, but this does not make a difference. Tried this with the http://github.com/rails/rails/commits/2-3-stable branch checked out moments ago.

    Thanks for any light you can shed!

    January 20th, 2010 @ 01:38 AM

  6. Scott Rushforth
    Scott Rushforth
    • Tag changed from 2.3.2, accepts_nested_attributes_for to 2.3.2, 2.3.6, accepts_nested_attributes_for

    January 20th, 2010 @ 06:24 PM

  7. David
    David

    As Scoot Rushforth described it, the patch doesn't solve the problem. The ActiveRecord::RecordNotFound exception should be raised only if the nested record is not found, not when the association is missing. In that case a new association in the join table should be created.

    The description of the method assign_nested_attributes_for_collection_association (nested_attributes.rb) says:

    Hashes with an :id value matching an existing associated record will update that record. Hashes without an :id value will build a new record for the association. Hashes with a matching :id value and a :_destroy key set to a truthy value will mark the matched record for destruction.

    If the id is not passed, a new record and a new association will be created.

    If the id is passed, the record will be updated (as described), but the association should be checked/created as well.

    In a nested form, the user should be able to either create a new (nested) record, or choose an existing one. Currently, choosing an existing record results in the ActiveRecord::RecordNotFound error.

    May 13th, 2010 @ 04:53 PM

  8. Ryan Bigg
    Ryan Bigg

    This ticket breaks our application. I've distilled it down to http://github.com/radar/rails-test-app/tree/anaf_has_one.

    May 31st, 2010 @ 07:55 AM

  9. José Valim
    José Valim
    • Milestone changed from 2.3.6 to 2.3.9
    • State changed from resolved to open
    • Assigned user changed from Eloy Duran to José Valim

    Hey Ryan, can you add a failing test to Rails test suite? In my understanding, the current patch is completely wrong, so feel free to revert it as well!

    May 31st, 2010 @ 08:00 AM

  10. Ryan Bigg
    Ryan Bigg

    This patch should duplicate the issue, but it's not. I have to leave work now (end of the day). As far as I know, this is what is happening.

    May 31st, 2010 @ 08:27 AM

  11. Sharad Jain
    Sharad Jain

    It seems, this bug is a side effect of another bug: 4766.

    June 7th, 2010 @ 03:54 PM

  12. George Montana Harkin
    George Montana Harkin

    running into the same issue with belongs_to relationships.

    June 9th, 2010 @ 07:41 PM

  13. George Montana Harkin
    George Montana Harkin
    • Tag changed from 2.3.2, 2.3.6, accepts_nested_attributes_for to rails 2.3.8, 2.3.2, 2.3.6, accepts_nested_attributes_for

    @Ryan,

    I think the test just needs an :id field.

    I've created a patch that solves our issues related to this bug. It fixes the problem by creating a new instance of the class if attributes['id'] is set.

    June 11th, 2010 @ 09:09 PM

  14. José Valim
    José Valim

    We need a failing test case in order to apply any patch. Thanks!

    June 11th, 2010 @ 09:27 PM

  15. George Montana Harkin
    George Montana Harkin

    Thanks for the note José. Attached is an updated test (which found issues in my patch.) and an updated patch (thanks to the tests).

    Apply the tests patch to see the issues. Apply the code patch to fix the tests.

    June 14th, 2010 @ 05:48 PM

  16. George Montana Harkin
    George Montana Harkin
    • Tag changed from rails 2.3.8, 2.3.2, 2.3.6, accepts_nested_attributes_for to 2.3.2, 2.3.6, 2.3.8, accepts_nested_attributes_for

    June 14th, 2010 @ 06:38 PM

  17. techy_bolek
    techy_bolek

    Same for me.

    class Part < ActiveRecord::Base
    end

    class Partquantity < ActiveRecord::Base
    belongs_to :part

    also same problem with has_one

    accepts_nested_attributes_for :part end

    <% form_for(@partquantity) do |pq_form| %>
    <%= pq_form.error_messages %>

    <% pq_form.fields_for :part do |part_form| %>

     <%= part_form.label :id, 'Select Part:' %>
     <%= part_form.select :id,  options_from_collection_for_select(@parts, 'id', 'code') %>
    
    <% end %> .... <% end %>

    Form submission results in the rollowing request attributes:
    {"authenticity_token"=>"K0AhiY3Uozqj9VpgqhswgXcNMNuO2Yzfgfp3xOgsQrs=", "partquantity"=>{"part_attributes"=>{"id"=>"2"}, "quantity"=>"ii"}, "commit"=>"Create"}

    and when I do @partquantity = Partquantity.new(params[:partquantity) I get:

    Couldn't find Part with ID=2 for Partquantity with ID=

    June 16th, 2010 @ 11:54 PM

  18. José Valim
    José Valim

    Hey George, thanks for the patch! Just two notes: could you please create them using the format described here:

    http://rails.lighthouseapp.com/projects/8994/sending-patches

    Also, it would be better if you used "reflect_on_association(association_name)" to retrieve associations (since it's the official API) instead of "reflections[association_name]".

    Thanks a bunch!

    June 23rd, 2010 @ 08:26 AM

  19. George Montana Harkin
    George Montana Harkin
    • Tag changed from 2.3.2, 2.3.6, 2.3.8, accepts_nested_attributes_for to 2.3.2, 2.3.6, 2.3.8, accepts_nested_attributes_for, patch

    José, An updated patch is attached.

    I've also created a branch in github if that is easier: http://github.com/harking/rails/tree/2415_fix_for_accepts_nested_at...

    June 23rd, 2010 @ 04:25 PM

  20. José Valim
    José Valim

    George, I already applied in the 2-3-stable branch. Could you please provide a patch for master?

    June 23rd, 2010 @ 04:32 PM

  21. José Valim
  22. Repository
    Repository
    • State changed from open to resolved

    (from [7d2173ec5c68e10807da96f4bc8bc6ab1e89c167]) Fixes #2415 by creating a new instance of the Model when saving attributes to that model and the associated attributes already exist. Tests included. [#2415 state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/7d2173ec5c68e10807da96f4bc8bc6...

    June 23rd, 2010 @ 04:39 PM

  23. Repository
    Repository
    • State changed from resolved to committed

    (from [7d2173ec5c68e10807da96f4bc8bc6ab1e89c167]) Fixes #2415 by creating a new instance of the Model when saving attributes to that model and the associated attributes already exist. Tests included. [#2415 state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/7d2173ec5c68e10807da96f4bc8bc6...

    June 23rd, 2010 @ 04:39 PM

  24. José Valim
    José Valim
    • State changed from committed to open

    Needs a patch for master.

    June 23rd, 2010 @ 04:40 PM

  25. Rohit Arondekar
    Rohit Arondekar
    • Importance changed from to

    Attached is a patch for master. I just manually applied the 2-3-stable patch. The tests pass so I didn't change anything. Also maintained ownership because George did all the hardwork! :)

    June 27th, 2010 @ 02:39 PM

  26. Repository
    Repository
    • State changed from open to resolved

    (from [0c0b0aa0f223523331afdc157fb3992a121bf497]) Fixes #2415 by creating a new instance of the Model when saving attributes to that model and the associated attributes already exist. Tests included. [#2415 state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/0c0b0aa0f223523331afdc157fb399...

    June 27th, 2010 @ 03:59 PM

  27. Repository
    Repository
    • State changed from resolved to committed

    (from [0c0b0aa0f223523331afdc157fb3992a121bf497]) Fixes #2415 by creating a new instance of the Model when saving attributes to that model and the associated attributes already exist. Tests included. [#2415 state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/0c0b0aa0f223523331afdc157fb399...

    June 27th, 2010 @ 03:59 PM

  28. George Montana Harkin
    George Montana Harkin
    • Tag changed from 2.3.2, 2.3.6, 2.3.8, accepts_nested_attributes_for, patch to 2.3.2, 2.3.6, 2.3.8, 3.0, accepts_nested_attributes_for, patch

    Thanks Rohit and José! RailsCommunity++

    June 28th, 2010 @ 04:21 PM

  29. scrozier
    scrozier

    This is preliminary, but I just installed 2-3-stable. It fixed one-level-deep nested attribute updating, but I am still seeing a problem when there is more than one level of nesting. In that case, it is looking like the "grandchildren" records are only updated if at least one attribute changes in the related "child" record. Otherwise, no update is done on the grandchildren.

    It's quite possible that this is my problem...anyone else?

    July 1st, 2010 @ 07:07 PM

  30. Rafael Cardoso
    Rafael Cardoso

    I'm also having the same problem with the update_attributes when using a two level deep nested resources. It will update the first level child but not the second level one. Should we open a new ticket or keep going in this one?

    July 28th, 2010 @ 05:50 PM

  31. Neeraj Singh
    Neeraj Singh

    @Rafael did you try with rails edge?

    If it is still an issue please open a new ticket and refer to this ticket as 'related'. Yours is related to grandchildren while original ticket is related to children. So lets keep them separate.

    July 28th, 2010 @ 06:17 PM

  32. Rafael Cardoso
    Rafael Cardoso

    @Neeraj I did not before, I just did check and in fact it is correct for the 2.3.9 version. Thank you.

    July 28th, 2010 @ 10:03 PM

  33. George Montana Harkin
  34. Ryan Bigg
    Ryan Bigg
    • State changed from committed to open

    Patch reverted, ticket resurrected.

    How rare.

    October 15th, 2010 @ 05:54 AM

  35. José Valim
    José Valim
    • State changed from open to wontfix

    No, we are not opening it back. The security bug is intrinsic to the feature asked here.

    If you want to implement the behavior asked in this ticket, you will be better of updating the nested records using ajax and the update the associations in the parent object using "#{association}_ids".

    October 15th, 2010 @ 07:37 AM

  36. Jeremy Kemper