Using accepts_nested_attributes_for with assign_attributes means immediate saving of associated model

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Using accepts_nested_attributes_for with assign_attributes means immediate saving of associated model

Jason Barnabe
Previously raised at https://github.com/rails/rails/issues/17368

When a parent model accepts_nested_attributes_for a child, and you use assign_attributes on an existing parent, the children are immediately persisted; assign_attributes is just calling children= on the parent. This results in the changes being half-saved and messes things up if you wanted to do further processing before saving.

I propose that for has_one, has_many, and has_and_belongs_to_many associations, assign_attribute avoid persisting by instead:

1. mark_for_destruction all existing children not present in the passed hash.
2. Update (but not persist) all existing children present in the passed hash.
3. Call children.build to create the new children.

I imagine this logic would go in _assign_attribute and would make use of reflect_on_association to figure out what's what. I'd be willing to attempt to implement this, if it's a change that would be desired.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Using accepts_nested_attributes_for with assign_attributes means immediate saving of associated model

Ross Philip
I think this would be a really good change and hope you decide to pursue it.  The current behavior is not intuitive; one would expect that assign_attributes(nested_params) not persist any changes; if I wanted to persist changes I would use update(nested_params).  I've been bitten by this and only after poring through the documentation realized why.

On Friday, April 17, 2015 at 1:00:22 AM UTC-6, Jason Barnabe wrote:
Previously raised at <a href="https://github.com/rails/rails/issues/17368" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Frails%2Frails%2Fissues%2F17368\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE4k2c_uROtfK53q7-SW0Dh0rM_ig&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Frails%2Frails%2Fissues%2F17368\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE4k2c_uROtfK53q7-SW0Dh0rM_ig&#39;;return true;">https://github.com/rails/rails/issues/17368

When a parent model accepts_nested_attributes_for a child, and you use assign_attributes on an existing parent, the children are immediately persisted; assign_attributes <a href="https://github.com/rails/rails/blob/master/activemodel/lib/active_model/attribute_assignment.rb#L46" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Frails%2Frails%2Fblob%2Fmaster%2Factivemodel%2Flib%2Factive_model%2Fattribute_assignment.rb%23L46\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGqKiIkeS0jnkHrR8uKE09hljj4JQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Frails%2Frails%2Fblob%2Fmaster%2Factivemodel%2Flib%2Factive_model%2Fattribute_assignment.rb%23L46\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGqKiIkeS0jnkHrR8uKE09hljj4JQ&#39;;return true;">is just calling children= on the parent. This results in the changes being half-saved and messes things up if you wanted to do further processing before saving.

I propose that for has_one, has_many, and has_and_belongs_to_many associations, assign_attribute avoid persisting by instead:

1. mark_for_destruction all existing children not present in the passed hash.
2. Update (but not persist) all existing children present in the passed hash.
3. Call children.build to create the new children.

I imagine this logic would go in _assign_attribute and would make use of reflect_on_association to figure out what's what. I'd be willing to attempt to implement this, if it's a change that would be desired.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.