views:

247

answers:

2

I'd like to add a begin...rescue block to one of my controllers create method, in order to log better info and construct the correct error message to return to the client. Does the rescue in any way 'interrupt' the rollback process?

I'm assuming rails automatically does a rollback. When does it happen? Has it already happened by the time I get in the rescue clause?

I'm using mySQL on Dreamhost and I think they use innoDB.

A: 

Just using begin...rescue isn't enough to rollback a transaction. You need to use:

ModelName.transaction do 
end

This is done explicitely on a call to save, so that all of your callbacks are executed together. What exceptions are you catching in your rescue block? What are you responding to? What kind of errors?

jonnii
I'm getting deadlocks. I don't think I'll have enough space here to describe it. It's for a card game. But in an after_save callback method for my PlayerAction model, I create another PlayerAction instance. I'm getting deadlocks on their related models. When that happens, I want to rollback the whole thing, including the first PlayerAction model and its relationships that were created.Sounds like you're saying that rails does NOT do automatic transactions, is that right? I have to explicitly start them and trigger a rollback? Is there a resource somewhere for this? I've been searching...
It does to explicit transactions but only across methods like save and update_attributes. So your after_save will run in the same transaction.
jonnii
I'm not sure what to suggest about deadlocks, sometimes you can re-order things to avoid them. There are a few plugins for retrying on deadlocks (http://github.com/rails/deadlock_retry). Might be worth looking at those too.
jonnii
+1  A: 

Here's the official documentation on transactions in Rails:

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

It may not be obvious from the docs, but the way to trigger a rollback is to raise ActiveRecord::Rollback, like this:

Model.transaction do
    model1.save!
    model2.save!

    # Check one more thing
    if something_is_wrong
        raise ActiveRecord::Rollback
    end
end

# Even if the transaction was rolled back via ActiveRecord::Rollback,
# execution will resume here, after the transaction block, which effectively
# catches the Rollback exception.
Rob Davis