lib/orphan_importer.rb
require_relative 'excel_upload'
require_relative 'import_orphan_settings'
class OrphanImporter
attr_accessor :import_errors, :settings
def initialize(file, partner)
@settings = ImportOrphanSettings.settings
@pending_orphans = []
@import_errors = []
@file = file
@partner = partner
@duplicates_hash = Hash.new([])
end
def extract_orphans
spreadsheet = upload_spreadsheet
import_orphans(spreadsheet) and check_for_duplicates
error_or_orphans
end
def valid?
import_errors.empty?
end
def import_orphans(doc)
return unless doc
settings.first_row.upto(doc.last_row){ |row| import_orphan(doc, row) }
end
def import_orphan(doc, row)
fields = parse_orphan(doc, row)
add_to_duplicates(fields, row)
check_orphan_validity(fields, row)
add_to_pending_orphans_if_valid(fields)
end
def parse_orphan(doc, row)
settings.columns.inject({}) do |memo, col_settings|
cell_val = doc.cell(row, col_settings.column)
memo[col_settings.field] = process_column row, col_settings, cell_val
memo
end
end
private
def add_import_errors(ref, error = nil)
@import_errors << { ref: ref, error: error }
end
def add_to_duplicates(fields, row)
hash_key = fields.select{ |k, _| %w[name father_name mother_name].include? k }
@duplicates_hash[hash_key] += [row]
end
def add_to_pending_orphans_if_valid(fields)
@pending_orphans << PendingOrphan.new(fields) if valid?
end
def check_for_duplicates
@duplicates_hash.values.select { |v| v.size > 1 }.each do |v|
add_import_errors "duplicate entries found on rows #{v.join(', ')}",
"Orphan's name, mother's name & father's name are the same."
end
end
def check_orphan_validity(fields, row)
orphan = PendingOrphan.new(fields).to_orphan
orphan.partner = @partner
orphan.orphan_list = OrphanList.new
unless orphan.valid?
add_import_errors "invalid orphan attributes for row #{row}",
orphan.errors.full_messages.join('; ')
end
end
def error_or_orphans
valid? ? @pending_orphans : @import_errors
end
def log_exceptions(row=nil,col_settings=nil)
begin
yield
rescue => e
message = e.to_s
message << " Error at row #{row}" if row
if col_settings
message << " for column #{col_settings.column}--#{col_settings.field}"
end
add_import_errors(e.class.name.split('::').last, message)
false
end
end
def process_column(row, col_settings, cell_val)
log_exceptions(row, col_settings) do
class_name = col_settings.type.split.first.classify
full_class = ("ImportOrphanSettings::#{class_name}Column").constantize
full_class.new(cell_val, col_settings).parse_value
end
end
def upload_spreadsheet
log_exceptions { ExcelUpload.upload(@file, settings.first_row) }
end
end