From 0145dfacbea4b499e6cc4c3144b77c4a3f84dcaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Immanuel=20H=C3=A4ussermann?= <hai@panter.ch>
Date: Thu, 31 May 2018 10:45:09 +0200
Subject: [PATCH] add default import behavior

---
 Gemfile.lock            | 12 ++++++++++++
 README.md               | 15 +++++++++++++--
 excelsior.gemspec       |  1 +
 lib/excelsior/import.rb | 18 +++++++++++++++---
 test/excelsior_test.rb  | 18 ++++++++++++++++++
 5 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index d88b4bb..0684b85 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,11 +2,20 @@ PATH
   remote: .
   specs:
     excelsior (0.1.0)
+      activesupport (~> 5.0)
       simple_xlsx_reader (~> 1.0.2)
 
 GEM
   remote: https://rubygems.org/
   specs:
+    activesupport (5.2.0)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
+      minitest (~> 5.1)
+      tzinfo (~> 1.1)
+    concurrent-ruby (1.0.5)
+    i18n (1.0.1)
+      concurrent-ruby (~> 1.0)
     mini_portile2 (2.3.0)
     minitest (5.11.3)
     nokogiri (1.8.2)
@@ -16,6 +25,9 @@ GEM
     simple_xlsx_reader (1.0.2)
       nokogiri
       rubyzip
+    thread_safe (0.3.6)
+    tzinfo (1.2.5)
+      thread_safe (~> 0.1)
 
 PLATFORMS
   ruby
diff --git a/README.md b/README.md
index b8491fb..19b9804 100644
--- a/README.md
+++ b/README.md
@@ -36,10 +36,21 @@ class UserImporter < Excelsior::Importer
 end
 ```
 
-Then create an instance of your import and run it:
+Create an instance of your import and run it. By default it infers the model
+to be imported from the classname, e.g.:
 
 ```ruby
-import = UserImport.new # you may also pass a file per instance here
+import = UserImport.new
+import.run # calls User.create!(row) for each row
+```
+
+### Extended API
+
+You may want to pass an excel file per instance. You can also define your own
+import behavior by passing a block to the `run` method:
+
+```ruby
+import = UserImport.new("users/all.xlsx")
 import.run do |row|
   User.create!(row) # raise an exception if the data doesn't match your expectations
 end
diff --git a/excelsior.gemspec b/excelsior.gemspec
index 550431c..2ebc529 100644
--- a/excelsior.gemspec
+++ b/excelsior.gemspec
@@ -26,4 +26,5 @@ Gem::Specification.new do |spec|
   spec.add_development_dependency "minitest", "~> 5.0"
 
   spec.add_runtime_dependency "simple_xlsx_reader", "~> 1.0.2"
+  spec.add_runtime_dependency "activesupport", "~> 5.0"
 end
diff --git a/lib/excelsior/import.rb b/lib/excelsior/import.rb
index cc58cca..23ed605 100644
--- a/lib/excelsior/import.rb
+++ b/lib/excelsior/import.rb
@@ -1,5 +1,6 @@
 require "simple_xlsx_reader"
-
+require "active_support"
+require "active_support/core_ext"
 require "excelsior/source"
 require "excelsior/mapping"
 
@@ -24,9 +25,14 @@ module Excelsior
       valid?
     end
 
-    def run(&block)
+    def run # takes an optional block
       @rows.map do |row|
-        yield map_row_values(row, @columns)
+        attributes = map_row_values(row, @columns)
+        if block_given?
+          yield attributes
+        else
+          model_class.create!(attributes)
+        end
       end
     end
 
@@ -40,5 +46,11 @@ module Excelsior
         acc
       end
     end
+
+    private
+
+    def model_class
+      self.class.name.gsub("Import", "").constantize
+    end
   end
 end
diff --git a/test/excelsior_test.rb b/test/excelsior_test.rb
index 4b6dcb2..536cafc 100644
--- a/test/excelsior_test.rb
+++ b/test/excelsior_test.rb
@@ -9,6 +9,19 @@ class UserImport < Excelsior::Import
   map "E-Mail", to: :email
 end
 
+class User
+  class << self
+    def create!(attributes)
+      @all ||= []
+      @all << attributes
+    end
+
+    def all
+      @all ||= []
+    end
+  end
+end
+
 class ExcelsiorTest < Minitest::Test
   def setup
     @import = UserImport.new
@@ -48,6 +61,11 @@ class ExcelsiorTest < Minitest::Test
   end
 
   def test_import_run
+    results = @import.run
+    assert_equal User.all.size, 2
+  end
+
+  def test_import_run_with_block
     results = @import.run { |v| v }
     assert_equal results[0], {
       firstname: "Hans",
-- 
GitLab