Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails transaction not rolling back

Why wouldn't this transaction rollback if even one create! fails? It's in a controller if that makes any difference.

def process_photos(photos)
  ActiveRecord::Base.transaction do
    begin
      photos.each do |photo|
        Photo.create!(creator_user: @user, buyer: @buyer, url: photo['url'])
      end
    rescue
      raise ActiveRecord::Rollback
    end
  end
end

I'm explicitly sending an array with some bad records. The good ones are getting created and the bad ones aren't but I need the whole thing to rollback if even one fails.

Here's my rspec test (passing a json array of photos) and it's incrementing.

expect { post :create, json }.not_to change(Photo, :count)
like image 924
kjs3 Avatar asked Jan 24 '14 19:01

kjs3


1 Answers

This was just a testing issue with rspec because you're already executing in a transaction in the test. It's the same nested transaction issue discussed here. In order to get the test to work you need to add…

requires_new: true

to the transaction call.

This fixed the test.

def process_photos(photos)
  ActiveRecord::Base.transaction(requires_new: true) do
    begin
      photos.each do |photo|
        Photo.create!(creator_user: @user, buyer: @buyer, url: photo['url'])
      end
    rescue
      raise ActiveRecord::Rollback
    end
  end
end

Important: Rollbacks will only work if your database engine supports them! For example MySQL with MyISAM doesn't support transactions, while MySQL with Inno DB does support them.

like image 184
kjs3 Avatar answered Nov 14 '22 01:11

kjs3