Verified Commit 8c9446f4 authored by Alexis Reigel's avatar Alexis Reigel
Browse files

`run` returns a result object

this new object contains everything related to the result, including the
report and the errors.
a new attribute is the status.
parent a39c6d52
Pipeline #20603 failed with stage
in 2 minutes and 8 seconds
......@@ -44,6 +44,18 @@ import = UserImport.new
import.run # calls User.create!(row) for each row
```
The result is an instance of `Excelsior::Result`:
```ruby
result = import.run
result.status
# => :succeeded
result.errors
# => { missing_column: [], model: [] }
result.report
# => #<struct Excelsior::Report inserted=2, failed=0>
```
### Model validation
A summary of the `ActiveRecord` model validations is available after running
......
......@@ -8,6 +8,7 @@ require 'excelsior/mapping'
require 'excelsior/error'
require 'excelsior/report'
require 'excelsior/transaction'
require 'excelsior/result'
module Excelsior
class Import
......@@ -15,8 +16,8 @@ module Excelsior
include Mapping
include Transaction
attr_accessor :source, :fields, :errors, :report
attr_accessor :rows, :columns
attr_accessor :source, :fields, :rows, :columns, :result
delegate :errors, :report, to: :result
def initialize(file = nil)
self.source = file || self.class.source_file
......@@ -28,7 +29,7 @@ module Excelsior
@columns = @sheet.rows.shift
@rows = @sheet.rows
@report = Report.new
@result = Result.new(@rows.length)
validate!
end
......@@ -40,23 +41,23 @@ module Excelsior
model_class.transaction do
insert_rows(&block)
raise ActiveRecord::Rollback if @report.failed.positive?
raise ActiveRecord::Rollback if report.failed.positive?
end
else
insert_rows(&block)
end
result
end
def validate!
@errors = fields.to_a.each_with_object({}) do |f, acc|
acc[:missing_column] ||= []
acc[:missing_column] << { missing: f[:header] } unless @columns.include?(f[:header])
fields.to_a.each do |f|
errors[:missing_column] << { missing: f[:header] } unless @columns.include?(f[:header])
end
end
def valid?
@errors[:missing_column].empty?
result.status != Result::Statuses::FAILED
end
private
......@@ -66,8 +67,6 @@ module Excelsior
end
def add_model_errors(record, index)
@errors[:model] ||= []
if record.errors.empty?
report_insert
return
......@@ -75,15 +74,15 @@ module Excelsior
report_failure
@errors[:model] << Error.new(index + 1, record.errors.full_messages)
errors[:model] << Error.new(index + 1, record.errors.full_messages)
end
def report_insert
@report.inserted += 1
report.inserted += 1
end
def report_failure
@report.failed += 1
report.failed += 1
end
def insert_rows(&block)
......
# frozen_string_literal: true
module Excelsior
Report = Struct.new(:inserted, :failed) do
Report = Struct.new(:expected, :inserted, :failed) do
def initialize(*args)
super(*args)
self.expected ||= 0
self.inserted ||= 0
self.failed ||= 0
end
......@@ -12,5 +13,9 @@ module Excelsior
def total
inserted + failed
end
def done?
expected == total
end
end
end
# frozen_string_literal: true
module Excelsior
class Result
module Statuses
PENDING = :pending
SUCCEEDED = :succeeded
FAILED = :failed
end
attr_accessor :errors, :report
def initialize(total_rows)
self.errors = {
missing_column: [],
model: []
}
self.report = Report.new(total_rows)
end
def status
return Statuses::FAILED if errors[:missing_column].any? || errors[:model].any?
if report.done?
Statuses::SUCCEEDED
else
Statuses::PENDING
end
end
end
end
......@@ -129,12 +129,20 @@ describe Excelsior do
@import.run
assert_equal User.all.size, 2
end
it 'returns a result object' do
result = @import.run
assert_equal Excelsior::Result::Statuses::SUCCEEDED, result.status
assert_equal Excelsior::Report.new(2, 2, 0), result.report
assert_equal({ missing_column: [], model: [] }, result.errors)
end
end
describe 'with a block' do
it 'yields the records to the block' do
results = @import.run { |v| v }
assert_equal results, [
it 'yields each record to the block' do
results = []
@import.run { |v| results << v }
assert_equal [
{
first_name: 'Hans',
last_name: 'Müller',
......@@ -145,7 +153,14 @@ describe Excelsior do
last_name: 'Brunz',
email: 'jb@runz.com'
}
]
], results
end
it 'returns a result object' do
result = @import.run { |v| v }
assert_equal Excelsior::Result::Statuses::SUCCEEDED, result.status
assert_equal Excelsior::Report.new(2, 2, 0), result.report
assert_equal({ missing_column: [], model: [] }, result.errors)
end
end
end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment