Save a list of objects in a transaction operation

932 views Asked by At

I'm trying to save in my postgres database a list of objects from a excel file. It must be done inside a transaction.

From the code below I can't rollback the transaction from invalid cases. The objects before some invalid case are saved, then the transaction is finished after.

class UploadFile < ApplicationRecord
  # Others validations 

  def save_from_file
    # open file 
    Product.transaction do
      begin
        (2..file.last_row).each do |n|
          product = Product.new(id: file.cell(n,1), price: file.cell(n,2))
          product.save!
        end
      rescue ActiveRecord::RecordInvalid
        raise ActiveRecord::Rollback
      end
    end
  end

end
1

There are 1 answers

0
pmnhaes On

Don't know if I completely understood your problem, but it seems like you wanted to rollback the whole transaction. In this case, your problem is this rescue.

According to Active Record Transactions :

Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you should be ready to catch those in your application code.

One exception is the ActiveRecord::Rollback exception, which will trigger a ROLLBACK when raised, but not be re-raised by the transaction block.

So, if you raise a rollback inside a rescue it won't trigger the transaction block to rollback, it just rolls back that specific object. In order to trigger the block to rollback it should be something like:

Product.transaction do
  (2..file.last_row).each do |n|
    product = Product.new(id: file.cell(n,1), price: file.cell(n,2))
    product.save!
  end
end

Like this it automatically raise rollback in the whole block once product.save! raise error.