This project is archived and is in readonly mode.
ActiveRecord::Rollback Does Not Work In Nested Transactions
Reported by Ken Collins | February 12th, 2009 @ 02:29 PM | in 2.x
While I was working on the latest SQL Server adapter for rails 2.3 I noticed this in the docs and that it does not work at all in all DBs/core.
# == Nested transactions
#
# #transaction calls can be nested. By default, this makes all database
# statements in the nested transaction block become part of the parent
# transaction. For example:
#
# User.transaction do
# User.create(:username => 'Kotori')
# User.transaction do
# User.create(:username => 'Nemu')
# raise ActiveRecord::Rollback
# end
# end
#
# User.find(:all) # => empty
I can totally see the issue but can not think of a good way to fix #transaction to let one block let another know this was set and hence all the block that finally answers true to transaction_open to do the work. I would love for some feedback for a way I might be able to patch this and/or if the docs should be changed to say that that exception class can only be used in the first transaction block.
BTW, there is a test in transaction_test.rb called #test_manually_rolling_back_a_transaction that I had copied but could never make it pass.
def test_manually_rolling_back_a_nested_transaction
Topic.transaction do
@first.approved = true
@first.save
Topic.transaction do
@second.approved = false
@second.save
raise ActiveRecord::Rollback
end
end
assert !Topic.find(1).approved?, "First shouldn't have been approved"
assert Topic.find(2).approved?, "Second should still be approved"
end
I believe Michael added this exception class, so I assigned him the ticket?
Comments and changes to this ticket
-
Michael Koziarski February 13th, 2009 @ 08:53 AM
Yeah, that's not possible, and can't be possible so the docs need updating.
If you raise another exception it'll rollback, but obviously AR::Rollback doesn't, and shouldn't, propagate.
-
Michael Koziarski February 13th, 2009 @ 08:54 AM
- Assigned user changed from Michael Koziarski to Pratik
Needs fixing in docrails
-
Ken Collins February 13th, 2009 @ 02:19 PM
Agreed, it was looking very hackish in my code attempts to implement this. And indeed the raising of some other exception does do the job.
I'll add the doc changes to support this and submit a patch soon.
-
Pratik February 13th, 2009 @ 02:23 PM
Hey Ken,
Just lemme know your github username and I'll give you commit access to docrails.
-
Ken Collins February 13th, 2009 @ 02:25 PM
Ah duh, I think I might already be on, it's "metaskills".
-
CancelProfileIsBroken April 22nd, 2009 @ 10:29 PM
- State changed from new to resolved
Fixed in docrails
-
Ken Collins April 23rd, 2009 @ 12:38 AM
Thanks to whomever got that in docrails, I've been a bit too busy lately.
-
Jason Yuen January 8th, 2010 @ 11:28 PM
- Tag changed from 2.3, activerecord, nested, rollback, transaction to 2, activerecord, nested, rollback, transaction
@Michael: I was wondering about your comment that "obviously AR::Rollback doesn't, and shouldn't, propagate." We are nesting our calls to #transaction without using :require_new. In this situation, we are observing that when we raise ActiveRecord::Rollback in our inner transaction block, the database transaction does not get rolled back.
User.transaction do User.create(:username => 'Kotori') User.transaction do User.create(:username => 'Nemu') raise ActiveRecord::Rollback end end
In this example, neither 'Kotori' nor 'Nemu' should exist in the database but they do. It seems like this is a bug so I've attached a patch (for 2.3.4 but it doesn't seem like the code has changed in master) which addresses this issue (unless of course, there is a reason why this isn't actually an issue). Basically, the rollback exception is always re-raised until we get to the outermost transaction block.
-
Jason Yuen January 8th, 2010 @ 11:29 PM
- Tag changed from 2, activerecord, nested, rollback, transaction to 2.3, activerecord, nested, rollback, transaction
-
Jason Yuen January 14th, 2010 @ 06:36 PM
- Tag changed from 2.3, activerecord, nested, rollback, transaction to 2, activerecord, nested, rollback, transaction
Sorry guys - I think I was a little overzealous with the patch and I hadn't fully thought through all the implications (e.g. how it affects the validation lifecycle). I have an operation in a nested transaction block that causes an ActiveRecord::StaleObjectError. Instead of letting the stale object error propagate, I was rescuing it and re-raising an ActiveRecord::Rollback, thinking that the rollback would propagate across transaction boundaries and rollback operations in outer transaction blocks. I guess I was just being lazy, hoping that I wouldn't have to explicitly handle the stale object error :)
Sorry again for the noise!
Jason
-
Jason Yuen January 14th, 2010 @ 06:37 PM
- Tag changed from 2, activerecord, nested, rollback, transaction to 2.3.x, activerecord, nested, rollback, transaction
-
Ryan Bigg October 9th, 2010 @ 09:56 PM
- Tag cleared.
- Importance changed from to Low
Automatic cleanup of spam.
-
Ivan Evtuhovich December 8th, 2010 @ 09:11 PM
You fix this only in docrails, but rdoc documentation is wrong (patch attached)
And i wonder why by default nested transaction rollback do not works?
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>