Browse files

Make nested_attributes plugin add newly created objects to cached ass…

…ociation array immediately

The reasoning behind this is that if this isn't done, the current
object has no way to access the nested attribute records until
after the save.

The general use case for nested_attributes is a web form that
handles dependent records.  Without any access to the nested
records, it is very difficult to handle validation failures
and display nice error messages to the user if dependent records
are not valid.

This approach adds the newly created records to the cached array,
so if validation fails, you can just iterate over the cached array,
and it will have both previously existing and new records in it.

This change does not affect many_to_one associations, since they
don't have a cached association array, and setting the object
in the cached association would probably cause issues.

This also doesn't affect updating existing records, since those
are already in the array.
  • Loading branch information...
1 parent b77fdab commit 14e8fd245d965e325294aaf985f57ff1bd088b86 @jeremyevans committed Oct 28, 2009
Showing with 9 additions and 0 deletions.
  1. +2 −0 CHANGELOG
  2. +1 −0 lib/sequel/plugins/nested_attributes.rb
  3. +6 −0 spec/extensions/nested_attributes_spec.rb
@@ -1,5 +1,7 @@
=== HEAD
+* Make nested_attributes plugin add newly created objects to cached association array immediately (jeremyevans)
* Make add_ association method not add the associated object to the cached array if it's already there (jeremyevans)
* Add Model#modified! for explicitly marking an object as modified, so save_changes/update will run callbacks even if no columns have been modified (jeremyevans)
@@ -88,6 +88,7 @@ def nested_attributes_create(reflection, attributes)
nested_attributes_set_attributes(reflection, obj, attributes)
after_validation_hook{validate_associated_object(reflection, obj)}
if reflection.returns_array?
+ send(reflection[:name]) << obj
after_save_hook{send(reflection.add_method, obj)}
# Don't need to validate the object twice if :validate association option is not false
@@ -72,6 +72,12 @@ def empty?; false; end
@mods.should == [[:is, :albums, {:name=>"Al"}, 1], [:is, :tags, {:name=>"T"}, 2], [:i, :at, {:album_id=>1, :tag_id=>2}, 3]]
+ it "should add new objects to the cached association array as soon as the *_attributes= method is called" do
+ a ={:name=>'Ar', :albums_attributes=>[{:name=>'Al', :tags_attributes=>[{:name=>'T'}]}]})
+ a.albums.should == [>'Al')]
+ a.albums.first.tags.should == [>'T')]
+ end
it "should support updating many_to_one objects" do
al = @Album.load(:id=>10, :name=>'Al')
ar = @Artist.load(:id=>20, :name=>'Ar')

0 comments on commit 14e8fd2

Please sign in to comment.