views:

35

answers:

2

I'm writing an import routine that will allow a user to upload a CSV file to load their database. Each row of the CSV corresponds to a model.

I'm using FasterCSV to read the file and split the data into individual models, which is working great. I'm just having trouble deciding on the best approach to handle errors.

Right now I have this going, but it really seems wrong to me:

def import(collection)
  begin
    self.transaction do
      collection.collect{|object| object.save!}
    end
  rescue ActiveRecord::RecordInvalid => invalid
    return false
  end

  return true
end

Is there a better way to save a collection of models?

A: 

For this problem I think the better approach is yours. Maybe not all the records in the csv aré going yo validare, and those that not doesnt matter (log them in order to know the errors)

pablorc
+2  A: 

Using an exception in a loop is going to cause all kinds of headaches for you when you want to track down the problematic record. What you might do is try and save them all, but report on those with errors:

 def import(collection)
   failed = nil

   transaction do
     failed = collection.reject { |r| r.save }

     unless (failed.empty?)
       raise ActiveRecord::Rollback
     end
   end

   failed
 end

This presumes you're interested in having a look at the errors. If any records fail, they will be returned in an Array. Otherwise you'll get a nil, which means no errors.

If you don't care, you can always just do a quick and dirty save:

def import(collection)
  transaction do
    collection.each(&:save!)
  end
end

This will pop an ActiveRecord::RecordInvalid exception for the first failure.

tadman