accepts_nested_attributes_for is Creating New Records; Gotcha!

Graham Jenson
Maori Geek
Published in
1 min readJan 29, 2015

--

accepts_nested_attributes_for is a really powerful method in Rails because it allows a model to alter related models through itself. However, it has a pretty big gotcha.

An example using accepts_nested_attributes_for is where a user model which belongs_to an alias model, i.e.

#user.rb
class User < ActiveRecord::Base
end
#alias.rb
class Alias < ActiveRecord::Base
belongs_to :user
accepts_nested_attributes_for :user
end

This allows the Alias model to change the user by passing a hash key user_attributes i.e.

Alias.first.user.name
>> "Alice"
Alias.first.update_attributes(
{
:user_attributes => {
:id => 1,
:name => "Bob"
}
})
Alias.first.user.name
>> "Bob"

The gotcha exists if you do not pass the :id symbol in the attributes hash, i.e.

Alias.first.user_id
>> 1
Alias.first.update_attributes(
{
:user_attributes => {
:name => "Bob"
}
})
Alias.first.user_id
>> 2

This behaviour is documented, it is just not what I would have expected.

To "fix" this (if you do not want to pass the id every time) you can set the :update_only flag to true, i.e.

#alias.rb
class Alias < ActiveRecord::Base
belongs_to :user
accepts_nested_attributes_for :user,
:update_only => true
end

--

--