Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does rails do a rollback if I use begin...rescue?

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.

like image 202
user26270 Avatar asked Apr 23 '10 17:04

user26270


3 Answers

I've been experimenting with this. It seems like if your rescue catches the exception that would have caused the rollback, the part of the transaction that already happened gets committed. In my case, I want the database rolled back to the way it was before the transaction started, but I still want to handle the exception.

I ended up with this:

self.transaction do
  first_operation
  begin
    operation_that_might_violate_db_constraint
  rescue ActiveRecord::RecordNotUnique
      #deal with the error
      raise ActiveRecord::Rollback #force a rollback
  end
end

The raise ActiveRecord::Rollback part makes sure the transaction gets completely rolled back. Without it, the changes from first_operation would end up getting committed.

The ActiveRecord::Rollback is a special kind of exception that doesn't bubble above the level of the transaction, so you won't end up with an uncaught exception that renders the error page.

I'm not sure this is the gold-standard way of doing this, but it seems to work.

like image 57
pseudopeach Avatar answered Oct 30 '22 14:10

pseudopeach


Rollback not be processed.

ex:

create_table "helps", :force => true do |t|
    t.string   "title",                           :null => false
    t.text     "content"
end

#Rails console
Help.transaction do
  Help.create! title: "aaa"
  begin
    Help.create! content: "111"
  rescue
    p "create error."
  end
  Help.create! title: "bbb"
end

#get this
>> "create error."
Help.count
>> 2
like image 35
Scott1473 Avatar answered Oct 30 '22 14:10

Scott1473


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?

like image 45
jonnii Avatar answered Oct 30 '22 13:10

jonnii