This project is archived and is in readonly mode.
accepts_nested_attributes_for on has_many does not update or delete if you also set validates_associated
Reported by swalterd | July 15th, 2010 @ 12:49 AM
Tested to be a problem in Rails 2.3.8 and working in Rails 2.3.5
If you have a has_many association with validation and then try
to update that association with update_attributes on a newly loaded
parent object, the validation will overload the objects updated in
memory before the save.
Example:
 class Address < ActiveRecord::Base
  belongs_to :contact
  validates_inclusion_of :is_current, :in => [true, false], :allow_nil => true  #any validation will do 
 end
 class Contact < ActiveRecord::Base
   has_many :addresses, :dependent => :destroy
   validates_associated :addresses    
   accepts_nested_attributes_for :addresses, :allow_destroy => true
 end
 #now create a new contact with an address
 company = Contact.create :name => "test"
 newaddress = company.addresses.create :city => "Austin", :is_current => true
 #now reload the company from the db
 company = Contact.find company.id
 #now update attributes
 company.update_attributes(:addresses_attributes => [{:id => newaddress.id, :city => "Dallas",  :is_current => true }]
 #now check the address city
 company.addresses.first.city
 #Will print out Austin
This is because the code in Rails 2.3.8 does not load the addresses
association for the nested attributes update. Instead it tries to
be clever and it loads only the objects for which it has IDs. This
saves time, but when validation runs in sees that
company.addresses.loaded? is false and it reloads the association,
and wipes out the changes.In activerecord/lib/active_record/nested_attributes.rb the code:
 existing_records = if association.loaded?
     association.to_a
   else
     attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact
     attribute_ids.present? ? association.all(:conditions => {association.primary_key => attribute_ids}) : []
   end</code>
Seems to be the problem. If I just change it to
 existing_records = association.to_a
I have no problems.In Rails 2.3.5 when it loops over the attributes array it uses this code to find the object
 existing_record = send(association_name).detect { |record| record.id.to_s == attributes['id'].to_s }
This will load the association the first time the detect is run,
and avoid the problem with validation.Comments and changes to this ticket
- 
        

Neeraj Singh July 15th, 2010 @ 03:42 AM
- Importance changed from  to Low
 
nested_attributes is totally broken in 2.3.8. Please try with 2-3-stable branch and let us know if the problem persists.
 - 
            
        

swalterd July 15th, 2010 @ 05:31 AM
It seems to work in Rails 2-3-stable but I will do more testing tomorrow.
 - 
            
        

swalterd July 15th, 2010 @ 04:24 PM
After more testing it appears that 2-3-stable checkout fixes the problem I was having.
 - 
        

Neeraj Singh July 15th, 2010 @ 04:44 PM
- State changed from new to invalid
 
 
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
Tags
Referenced by
- 
        
          5304 
          rails3: accepts_nested_attributes_for + validated_associated = no updates
        #5115 describes this problem pretty well for
rails 2.3.8....