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....