1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.