This is my importer to database from excel file. I would like to handle situations when any error raise. To not breaks whole import when one errors occurs.
For example when there is duplicated record and I have uniqueness validations. I would like to store this row id in errors table and inform about that at the end.
class DDImporter
attr_accessor :file
def initialize(path)
@path = path
end
def open
@file = Roo::Excelx.new(@path)
end
def sheets
@file.sheets
end
def extract_sheets
sheets.each do |sheet|
unless sheet == ("risks" || "allergies_symptoms")
extract sheet
end
end
end
def extract sheet_name
@file.default_sheet = sheet_name
header = file.row 1
2.upto(file.last_row) do |i|
row = Hash[[header, file.row(i)].transpose]
# row.delete "id"
object = sheet_name.classify.constantize
object.create!(row)
end
end
end
1 Answer 1
It can be as simple as :
def initialize(path)
@path = path
@imported = []
@errors = []
end
def extract sheet_name
@file.default_sheet = sheet_name
header = file.row 1
2.upto(file.last_row) do |i|
row = Hash[[header, file.row(i)].transpose]
# row.delete "id"
model = sheet_name.classify.constantize
# this is the part that gets the job done.
object = model.new(row)
if object.save
@imported << object
else
@rejected << object
end
end
end
... this way you can iterate through @imported
or @rejected
at the end of the import process (to display errors, or perform additional tasks).
This code can also easily be adapted to only catch exceptions :
def extract sheet_name
@file.default_sheet = sheet_name
header = file.row 1
2.upto(file.last_row) do |i|
row = Hash[[header, file.row(i)].transpose]
# row.delete "id"
object = sheet_name.classify.constantize
object.create!(row)
end
rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid => error
# rejected record for these errors can be accessed with :
error.record
# to resume processing, just :
error.continue
end
Explore related questions
See similar questions with these tags.