Add local_census_records importation model

This model without database allow us to validate incoming file extension and
headers and also does the following during importation process:

* Ignore empty rows
* Classifiy rows in two groups: created_records, invalid_records
This commit is contained in:
Senén Rodero Rodríguez
2019-05-16 10:56:44 +02:00
committed by Javi Martín
parent 0239efef9d
commit 615bfadca8
8 changed files with 218 additions and 1 deletions

View File

@@ -0,0 +1,84 @@
require "csv"
class LocalCensusRecords::Import
include ActiveModel::Model
ATTRIBUTES = %w[document_type document_number date_of_birth postal_code].freeze
ALLOWED_FILE_EXTENSIONS = %w[csv].freeze
attr_accessor :file, :created_records, :invalid_records
validates :file, presence: true
validate :file_extension, if: -> { @file.present? }
validate :file_headers_definition, if: -> { @file.present? && valid_extension? }
def initialize(attributes = {})
if attributes.present?
attributes.each do |attr, value|
public_send("#{attr}=", value)
end
end
@created_records = []
@invalid_records = []
end
def save
return false if invalid?
CSV.open(file.path, headers: true).each do |row|
next if empty_row?(row)
process_row row
end
true
end
private
def process_row(row)
local_census_record = build_local_census_record(row)
if local_census_record.invalid?
invalid_records << local_census_record
else
local_census_record.save
created_records << local_census_record
end
end
def build_local_census_record(row)
local_census_record = LocalCensusRecord.new
local_census_record.attributes = row.to_hash.slice(*ATTRIBUTES)
local_census_record
end
def empty_row?(row)
row.all? { |_, cell| cell.nil? }
end
def file_extension
return if valid_extension?
errors.add :file, :extension, valid_extensions: ALLOWED_FILE_EXTENSIONS.join(", ")
end
def fetch_file_headers
CSV.open(file.path, &:readline)
end
def file_headers_definition
headers = fetch_file_headers
return if headers.all? {|header| ATTRIBUTES.include? header } &&
ATTRIBUTES.all? {|attr| headers.include? attr }
errors.add :file, :headers, required_headers: ATTRIBUTES.join(", ")
end
def valid_extension?
ALLOWED_FILE_EXTENSIONS.include? extension
end
def extension
File.extname(file.original_filename).delete(".")
end
end