This project is archived and is in readonly mode.

#3525 ✓resolved

Nested attributes are saved twice

Reported by gix | November 30th, 2009 @ 09:56 PM | in 2.3.6

Nested attributes are saved twice. Suppose a definition like this, each having a name column:

    class Person < ActiveRecord::Base
        has_many :children
        accepts_nested_attributes_for :children

    class Child < ActiveRecord::Base
        belongs_to :person
        before_save do
            puts "before save"

Creating a person with nested attributes reveils that the child is saved twice (i.e. insert+update, or update+update):

>> Person.create(:name=>'Person',:children_attributes=>[{:name=>'Child'}])
before save!
before save!
=> #<Person id: 1, name: "Person", child_id: nil, created_at: "2009-11-30 21:26:44", updated_at: "2009-11-30 21:26:44">

This usually won't result in two queries though, since the dirty-feature removes all updated columns after the first save:

SQL (0.1ms)   BEGIN
Person Create (0.4ms)   INSERT INTO `people` (`name`, `created_at`, `updated_at`, `child_id`) VALUES('Person', '2009-11-30 21:27:15', '2009-11-30 21:27:15', NULL)
Child Create (0.2ms)   INSERT INTO `children` (`name`, `created_at`, `updated_at`) VALUES('Child', '2009-11-30 21:27:15', '2009-11-30 21:27:15')
SQL (1.3ms)   COMMIT

The reason for this is that AutosaveAssociation#save_collection_association is set up twice as an after-callback for create and update: first when calling has_many :children (AutosaveAssociation overwrites has_many et al and adds a call to add_autosave_association_callbacks), and second when calling accepts_nested_attributes_for (calls add_autosave_association_callbacks right after defining the nested attributes setter). So in turn the save method is overwritten with an equivalent one, and added again as a callback.

I'm not sure what would be the best way to fix this (or whether this is actually intended behavior). The call to add_autosave_association_callbacks should probably be dropped from accepts_nested_attributes_for since it requires an association anyway. Otherwise a simple return if method_defined? save_method at the top of add_autosave_association_callbacks works, but only cures the symptom.

Comments and changes to this ticket

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=""></a>