This project is archived and is in readonly mode.
associations do not autosave when a child is modified by creating a "grandchild" thru nested attributes
Reported by sarah (at ultrasaurus) | June 20th, 2009 @ 04:19 AM | in 2.x
accepts_nested_attributes_for is fabulous, but we've run into an issue where an object in our hierarchy doesn't save when we think it should.
Here's a test case that fails when added to: autosave_association_test.rb in the rails 2-3-stable branch
Pirate (new object)
|
|-> Ship (existing object identified by id)
|
|-> ShipPart (new object)
The ShipPart fails to save when saving Pirate. Both Pirate and Ship use accepts_nested_attributes to permit creation of the next lower child via attribute assignments.
Our speculation of the source of this bug is that autosave does not cascade past objects are are not new_record? or whose attributes are not changed?
class TestDeepAutosaveAssociation < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
Ship.accepts_nested_attributes_for :parts
@ship = Ship.create!(:name => "Bounty")
assert_not_nil @ship
end
def test_that_new_grandchild_will_save_when_child_exists
assert_difference "Pirate.count", 1 do
assert_difference "ShipPart.count", 1 do
assert_no_difference "Ship.count" do
@pirate = Pirate.create!(:catchphrase => "Arhh!",
:ship_attributes => { :id => @ship.id,
:parts_attributes => [ {:name => "plank"} ] })
end
end
end
end
end
Comments and changes to this ticket
-
sarah (at ultrasaurus) June 20th, 2009 @ 04:46 AM
We've discovered that if this is done without nested attributes it works fine. The following test passes:
class TestDeepAutosaveAssociationRevised < ActiveRecord::TestCase self.use_transactional_fixtures = false def setup Ship.accepts_nested_attributes_for :parts @ship = Ship.create!(:name => "Bounty") assert_not_nil @ship end def test_that_new_grandchild_will_save_when_child_exists assert_difference "Pirate.count", 1 do assert_difference "ShipPart.count", 1 do assert_no_difference "Ship.count" do @pirate = Pirate.new(:catchphrase => "Arhh!") @pirate.ship = @ship @ship.parts.build(:name => "plank") @pirate.save! end end end end end
-
Eloy Duran June 20th, 2009 @ 12:19 PM
- Assigned user set to Eloy Duran
-
sarah (at ultrasaurus) June 20th, 2009 @ 06:29 PM
Eloy -- thanks for taking this on. Now that I've looked at the code a little, I'm quite curious about this (aside from the practical need for a fix). We looked into this last night but couldn't really understand the autosave mechanism. In the second test which passes, how does Rails know that it needs to save the ship when @ship.changed? is false and only its association "parts" has changed?
-
Eloy Duran July 12th, 2009 @ 01:20 PM
- State changed from new to hold
Yes you are quite right, this is the problem. I haven't worked out yet how I'm going to fix this. But after breaking my head over it for a few hours I came to the conclusion that I don't have the right idea atm. I'll be on vacation for the next 3 weeks, so I hope that will clear my thoughts and I can come up with the right one when I'm back.
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="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>