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
end
class Child < ActiveRecord::Base
belongs_to :person
before_save do
puts "before save"
end
end
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.