importo 2.0.5 → 3.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -5
  3. data/Rakefile +16 -17
  4. data/app/controllers/concerns/maintenance_standards.rb +1 -1
  5. data/app/controllers/importo/imports_controller.rb +15 -12
  6. data/app/helpers/importo/application_helper.rb +11 -11
  7. data/app/importers/concerns/exportable.rb +31 -24
  8. data/app/importers/concerns/importable.rb +144 -62
  9. data/app/importers/concerns/importer_dsl.rb +6 -14
  10. data/app/importers/concerns/original.rb +23 -23
  11. data/app/importers/concerns/result_feedback.rb +62 -44
  12. data/app/importers/concerns/revertable.rb +11 -12
  13. data/app/importers/importo/base_importer.rb +16 -4
  14. data/app/importers/importo/import_job_callback.rb +29 -0
  15. data/app/jobs/importo/import_job.rb +40 -0
  16. data/app/mailers/importo/application_mailer.rb +2 -2
  17. data/app/models/importo/import.rb +35 -8
  18. data/app/models/importo/result.rb +5 -0
  19. data/app/services/importo/import_service.rb +1 -3
  20. data/app/services/importo/revert_service.rb +1 -1
  21. data/app/tables/importo/imports_table.rb +13 -17
  22. data/app/tables/importo/mensa_imports_table.rb +35 -0
  23. data/app/views/importo/imports/index.html.slim +6 -2
  24. data/app/views/importo/imports/new.html.slim +30 -20
  25. data/config/locales/en.yml +21 -9
  26. data/config/locales/nl.yml +10 -4
  27. data/config/routes.rb +4 -4
  28. data/db/migrate/20180409151031_create_importo_import.rb +9 -9
  29. data/db/migrate/20180628175535_add_locale_importo_import.rb +1 -1
  30. data/db/migrate/20230510051447_remove_result_from_imports.rb +5 -0
  31. data/db/migrate/20230510083043_create_importo_results.rb +11 -0
  32. data/lib/generators/importo/importer_generator.rb +1 -1
  33. data/lib/generators/importo/install_generator.rb +7 -8
  34. data/lib/generators/importo/templates/importo.rb +11 -0
  35. data/lib/generators/satis/install_generator.rb +22 -0
  36. data/lib/generators/satis/tailwind_config_generator.rb +24 -0
  37. data/lib/generators/satis/templates/config/initializers/satis.rb +13 -0
  38. data/lib/importo/acts_as_import_owner.rb +1 -1
  39. data/lib/importo/configuration.rb +52 -49
  40. data/lib/importo/engine.rb +11 -9
  41. data/lib/importo/import_column.rb +18 -6
  42. data/lib/importo/test_helpers.rb +19 -0
  43. data/lib/importo/version.rb +1 -1
  44. data/lib/importo.rb +12 -17
  45. metadata +75 -24
  46. data/app/services/importo/callback_service.rb +0 -14
  47. data/lib/generators/templates/importo.rb +0 -21
  48. /data/lib/generators/{templates → importo/templates}/README +0 -0
  49. /data/lib/generators/{templates → importo/templates}/application_importer.rb +0 -0
  50. /data/lib/generators/{templates → importo/templates}/importer.rb +0 -0
@@ -1,24 +1,34 @@
1
- = sts.form_for(@import) do |f|
2
- = f.input :kind, as: :hidden
3
- = sts.card title: t('.title'), icon: 'fad fa-file-spreadsheet' do |card|
4
- - card.action
5
- = f.submit
1
+ .grid.grid-cols-1.gap-4.sm:grid-cols-3.mt-4
2
+ .col-span-3.sm:col-span-3
3
+ = sts.form_for(@import) do |f|
4
+ = f.input :kind, as: :hidden
5
+ = sts.card :"importo_imports #{@import.kind}", title: t('.title'), icon: 'fad fa-file-spreadsheet' do |card|
6
+ - card.with_action
7
+ = f.submit
6
8
 
7
- .grid.grid-cols-12.gap-4
8
- .col-span-12
9
- .prose
10
- p= t('.explanation_html', name: @import.importer.class.friendly_name, sample_path: sample_import_path(kind: @import.kind))
11
- - if @import.allow_export?
12
- p= t('.export_html', export_path: export_path(kind: @import.kind))
9
+ .grid.grid-cols-12.gap-4
10
+ .col-span-12
11
+ .prose
12
+ p= t('.explanation_html', name: @import.importer.class.friendly_name, sample_path: sample_import_path(kind: @import.kind))
13
+ - if @import.allow_export?
14
+ p= t('.export_html', export_path: export_path(kind: @import.kind))
13
15
 
14
- .col-span-12
15
- - @import.importer.overridable_columns.each do |column|
16
- = f.fields_for :column_overrides do |fff|
17
- - if column.collection
18
- = fff.input column.attribute, as: :select, label: column.name, collection: column.collection, include_blank: true, required: false
19
- - else
20
- = fff.input column.attribute, label: column.name, required: false
16
+ .col-span-12
17
+ - @import.importer.overridable_columns.each do |column|
18
+ = f.fields_for :column_overrides do |fff|
19
+ - if column.collection
20
+ = fff.input column.attribute, as: :select, label: column.name, collection: column.collection, include_blank: true, required: false
21
+ - else
22
+ = fff.input column.attribute, label: column.name, required: false
21
23
 
22
- .col-span-12
23
- = f.input :original, as: :file
24
+ .col-span-12
25
+ = f.input :original, as: :file
26
+
27
+ .grid.grid-cols-1.gap-4.sm:grid-cols-3.mt-4
28
+ .col-span-3.sm:col-span-3
29
+ = sts.card :importo_imports, title: "#{@import.kind.humanize} imports", icon: 'fad fa-file-import', content_padding: false do |card|
30
+ - if defined? Mensa
31
+ = sts.mensa(:importo_mensa_imports, parameters: { kind: @import.kind })
32
+ - else
33
+ = card.with_table(:importo_imports, parameters: { kind: @import.kind }, custom_views: false)
24
34
 
@@ -1,8 +1,8 @@
1
1
  en:
2
2
  helpers:
3
- submit:
4
- importo/import:
5
- create: "Import"
3
+ submit:
4
+ importo/import:
5
+ create: "Import"
6
6
  importo:
7
7
  sheet:
8
8
  results:
@@ -10,24 +10,36 @@ en:
10
10
  explanation:
11
11
  name: Explanation
12
12
  column: Column
13
- explanation: Explanation
13
+ value: Value
14
+ explanation: Purpose
15
+ example: Example
14
16
  imports:
15
17
  index:
16
18
  title: Import results
19
+ card:
20
+ importo_imports:
21
+ title: Import results
22
+ tab:
23
+ Imports: Imports
17
24
  new:
18
- submit: 'Import'
25
+ submit: "Import"
19
26
  title: Import
20
27
  explanation_html: A CSV or Excel file can be used to import records. The first row should be the column names.<br>If an <b>id</b> is supplied it will update the matching record instead of creating a new one.<br>Download a <a href='%{sample_path}' target='_blank'>sample template</a> with all supported column names and their explanation.
21
28
  export_html: You can download the currently stored records.<br>Download the <a href='%{export_path}' target='_blank'>current data</a> with all supported columns
22
- error_explanation: 'The following problems prohibited this import from completing:'
29
+ error_explanation: "The following problems prohibited this import from completing:"
23
30
  import: Import %{kind}
24
31
  import_button: Import
32
+ card:
33
+ importo_imports:
34
+ tab:
35
+ importo_imports: Imports
25
36
  create:
26
37
  flash:
27
38
  no_file: Import failed, please upload a file.
28
- error: Import failed, there were problems.
29
- success: 'Import scheduled with id %{id}, you will get an email with the results.'
39
+ error: Import failed, there were problems %{error}.
40
+ success: "Import scheduled with id %{id}, you will get an email with the results."
30
41
  errors:
31
- structure_invalid: 'The structure is invalid, these are the invalid headers: %{invalid_headers}'
42
+ parse_error: "We encountered a parse error: %{error}"
43
+ structure_invalid: "The structure is invalid, these are the invalid headers: %{invalid_headers}"
32
44
  importers:
33
45
  result_message: "Successfully imported %{nr} of %{of} rows"
@@ -6,23 +6,29 @@ nl:
6
6
  explanation:
7
7
  name: Uitleg
8
8
  column: Kolom
9
- explanation: Uitleg
9
+ value: Waarde
10
+ explanation: Doeleinde
11
+ example: Voorbeeld
10
12
  imports:
11
13
  index:
12
14
  title: Import resultaten
15
+ card:
16
+ importo_imports:
17
+ title: Imports
13
18
  new:
14
19
  import:
15
20
  title: Importeer
16
21
  explanation_html: Een CSV of Excel bestand kan gebruikt worden om records te importeren. De eerste rij moet de kolom namen bevatten.<br>Als een <b>id</b> is ingevuld, zal het bestaande record worden geupdate in plaats van een nieuwe aan te maken.<br>Download een <a href='%{sample_path}' target='_blank'>voorbeeld file</a> met alle ondersteunde kolomnamen en de bijbehorende uitleg.
17
- error_explanation: 'De import is mislukt door de volgende problemen:'
22
+ error_explanation: "De import is mislukt door de volgende problemen:"
18
23
  import: Import %{kind}
19
24
  import_button: Importeer
20
25
  create:
21
26
  flash:
22
27
  no_file: Import mislukt, upload een bestand.
23
28
  error: Import mislukt, er waren problemen, voor details zie hieronder.
24
- success: 'Import geplanned met id %{id}, je krijgt een email met de resultaten.'
29
+ success: "Import geplanned met id %{id}, je krijgt een email met de resultaten."
25
30
  errors:
26
- structure_invalid: 'The structuur is ongeldig, dit zijn de ongeldige headers: %{invalid_headers}'
31
+ parse_error: "We ondervonden een parse error: %{error}"
32
+ structure_invalid: "The structuur is ongeldig, dit zijn de ongeldige headers: %{invalid_headers}"
27
33
  importers:
28
34
  result_message: "%{nr} van %{of} rijen succesvol geimporteerd"
data/config/routes.rb CHANGED
@@ -6,8 +6,8 @@ Importo::Engine.routes.draw do
6
6
  post :undo
7
7
  end
8
8
  end
9
- get ':kind/new', to: 'imports#new', as: :new_import
10
- get ':kind/sample', to: 'imports#sample', as: :sample_import
11
- get ':kind/export', to: 'imports#export', as: :export
12
- root to: 'imports#index'
9
+ get ":kind/new", to: "imports#new", as: :new_import
10
+ get ":kind/sample", to: "imports#sample", as: :sample_import
11
+ get ":kind/export", to: "imports#export", as: :export
12
+ root to: "imports#index"
13
13
  end
@@ -1,19 +1,19 @@
1
1
  class CreateImportoImport < ActiveRecord::Migration[5.1]
2
2
  def change
3
- enable_extension 'uuid-ossp'
4
- enable_extension 'pgcrypto'
3
+ enable_extension "uuid-ossp"
4
+ enable_extension "pgcrypto"
5
5
 
6
6
  return if table_exists?(:importo_imports)
7
7
 
8
8
  create_table :importo_imports, id: :uuid do |t|
9
- t.string :importo_ownable_type, null: false
10
- t.uuid :importo_ownable_id, null: false
9
+ t.string :importo_ownable_type, null: false
10
+ t.uuid :importo_ownable_id, null: false
11
11
 
12
- t.string :kind
13
- t.string :state
14
- t.string :file_name
15
- t.string :result_message
16
- t.jsonb :results
12
+ t.string :kind
13
+ t.string :state
14
+ t.string :file_name
15
+ t.string :result_message
16
+ t.jsonb :results
17
17
 
18
18
  t.timestamps
19
19
  end
@@ -2,6 +2,6 @@ class AddLocaleImportoImport < ActiveRecord::Migration[5.1]
2
2
  def change
3
3
  return if column_exists?(:importo_imports, :locale)
4
4
 
5
- add_column :importo_imports, :locale, :string, default: 'en'
5
+ add_column :importo_imports, :locale, :string, default: "en"
6
6
  end
7
7
  end
@@ -0,0 +1,5 @@
1
+ class RemoveResultFromImports < ActiveRecord::Migration[7.0]
2
+ def change
3
+ remove_column :importo_imports, :results, :jsonb
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class CreateImportoResults < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :importo_results, id: :uuid do |t|
4
+ t.integer :row_index
5
+ t.references :import, type: :uuid, null: false, foreign_key: {to_table: :importo_imports}
6
+ t.jsonb :details, default: {}
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,6 @@
1
1
  module Importo
2
2
  class ImporterGenerator < Rails::Generators::NamedBase
3
- source_root File.expand_path('../templates', __FILE__)
3
+ source_root File.expand_path("templates", __dir__)
4
4
 
5
5
  def copy_initializer_file
6
6
  template "application_importer.rb", "app/importers/application_importer.rb"
@@ -1,26 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/generators/base'
3
+ require "rails/generators/base"
4
4
 
5
5
  module Importo
6
6
  module Generators
7
-
8
7
  class InstallGenerator < Rails::Generators::Base
9
- source_root File.expand_path('../templates', __dir__)
8
+ source_root File.expand_path("../templates", __dir__)
10
9
 
11
- desc 'Creates a Importo initializer and copy locale files to your application.'
10
+ desc "Creates a Importo initializer and copy locale files to your application."
12
11
 
13
12
  def copy_initializer
14
- template 'importo.rb', 'config/initializers/importo.rb'
13
+ template "importo.rb", "config/initializers/importo.rb"
15
14
  end
16
15
 
17
16
  def copy_locale
18
- copy_file '../../../config/locales/en.yml', 'config/locales/importo.en.yml'
19
- copy_file '../../../config/locales/nl.yml', 'config/locales/importo.nl.yml'
17
+ copy_file "../../../config/locales/en.yml", "config/locales/importo.en.yml"
18
+ copy_file "../../../config/locales/nl.yml", "config/locales/importo.nl.yml"
20
19
  end
21
20
 
22
21
  def show_readme
23
- readme 'README' if behavior == :invoke
22
+ readme "README" if behavior == :invoke
24
23
  end
25
24
  end
26
25
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Importo.setup do |config|
4
+ config.base_controller = "::ApplicationController"
5
+ config.admin_authentication_module = "Authenticated"
6
+
7
+ # Current import owner
8
+ config.current_import_owner = -> { Current.user }
9
+
10
+ config.queue_name = :import
11
+ end
@@ -0,0 +1,22 @@
1
+ module Satis
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ def create_initializer_file
6
+ template "config/initializers/satis.rb"
7
+ end
8
+
9
+ def add_route
10
+ return if Rails.application.routes.routes.detect { |route| route.app.app == Satis::Engine }
11
+ route %(mount Satis::Engine => "/satis")
12
+ end
13
+
14
+ def copy_migrations
15
+ rake "satis:install:migrations"
16
+ end
17
+
18
+ def tailwindcss_config
19
+ rake "satis:tailwindcss:config"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require "rails/generators/base"
2
+
3
+ module Satis
4
+ module Generators
5
+ class TailwindConfigGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __dir__)
7
+ desc "Configures tailwind.config.js and application.tailwindcss.css"
8
+
9
+ def add_content_to_tailwind_config
10
+ inject_into_file "config/tailwind.config.js", before: "],\n theme: {" do
11
+ " // Satis content\n" +
12
+ %w[/app/views/**/* /app/helpers/**/* /app/controllers/**/* /app/components/**/* /app/javascript/**/*.js /app/assets/**/*.css].map { |path| " \"#{Satis::Engine.root}#{path}\"" }.join(",\n") +
13
+ ",\n "
14
+ end
15
+ end
16
+
17
+ def add_content_application_tailwind_css
18
+ inject_into_file "app/assets/stylesheets/application.tailwind.css", before: "@tailwind base;" do
19
+ "@import '#{Satis::Engine.root}/app/assets/stylesheets/satis/application.css';\n"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ Satis.setup do |config|
4
+ config.submit_on_enter = false
5
+
6
+ config.logger = Rails.logger
7
+ config.confirm_before_leave = false
8
+ config.current_user = -> { Current.user }
9
+
10
+ config.default_help_text = lambda do |template, object, key, additional_scope|
11
+ I18n.t((["help"] + [key.to_s]).join("."), default: nil)
12
+ end
13
+ end
@@ -5,7 +5,7 @@ module Importo
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- has_many :import, as: :importo_ownable, class_name: 'Importo::Import'
8
+ has_many :import, as: :importo_ownable, class_name: "Importo::Import"
9
9
  end
10
10
  end
11
11
  end
@@ -1,68 +1,71 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Importo
4
- class Configuration
5
- attr_accessor :admin_authentication_module
6
- attr_accessor :base_controller
7
- attr_accessor :base_service
8
- attr_accessor :base_service_context
9
- attr_accessor :queue_name
10
-
11
- attr_writer :logger
12
- attr_writer :current_import_owner
13
- attr_writer :import_callbacks
14
- attr_writer :admin_visible_imports
15
- attr_writer :admin_can_destroy
16
- attr_writer :admin_extra_links
17
-
18
- def initialize
19
- @logger = Logger.new(STDOUT)
20
- @logger.level = Logger::INFO
21
- @base_controller = '::ApplicationController'
22
- @base_service = '::ApplicationService'
23
- @base_service_context = '::ApplicationContext'
24
- @current_import_owner = -> {}
25
- @import_callbacks = {
26
- importing: lambda do |_import|
27
- end,
28
- completed: lambda do |_import|
29
- end,
30
- failed: lambda do |_import|
31
- end
32
- }
33
- @queue_name = :import
4
+ module Options
5
+ module ClassMethods
6
+ def option(name, default: nil)
7
+ attr_accessor(name)
8
+ schema[name] = default
9
+ end
34
10
 
35
- @admin_visible_imports = -> { Importo::Import.where(importo_ownable: current_import_owner) }
36
- @admin_can_destroy = ->(_import) { false }
37
-
38
- # Extra links relevant for this import: { link_name: { icon: 'far fa-..', url: '...' } }
39
- @admin_extra_links = ->(_import) { }
11
+ def schema
12
+ @schema ||= {}
13
+ end
40
14
  end
41
15
 
42
- # Config: logger [Object].
43
- def logger
44
- @logger.is_a?(Proc) ? instance_exec(&@logger) : @logger
16
+ def set_defaults!
17
+ self.class.schema.each do |name, default|
18
+ instance_variable_set(:"@#{name}", default)
19
+ end
45
20
  end
46
21
 
47
- def current_import_owner
48
- raise 'current_import_owner should be a Proc' unless @current_import_owner.is_a? Proc
49
- instance_exec(&@current_import_owner)
22
+ def self.included(cls)
23
+ cls.extend(ClassMethods)
50
24
  end
25
+ end
26
+
27
+ class Configuration
28
+ include Options
29
+
30
+ option :logger, default: Rails.logger
31
+ option :admin_authentication_module
32
+ option :base_controller, default: "::ApplicationController"
33
+ option :base_service, default: "::ApplicationService"
34
+ option :base_service_context, default: "::ApplicationContext"
35
+ option :current_import_owner, default: lambda {}
36
+ option :queue_name, default: :import
37
+
38
+ option :admin_visible_imports, default: lambda { Importo::Import.where(importo_ownable: Importo.config.current_import_owner) }
39
+ option(:admin_can_destroy,
40
+ default: lambda do |import|
41
+ false
42
+ end)
43
+
44
+ # Extra links relevant for this import: { link_name: { icon: 'far fa-..', url: '...' } }
45
+ option(:admin_extra_links,
46
+ default: lambda do |import|
47
+ []
48
+ end)
51
49
 
52
- def import_callback(import, state)
53
- instance_exec(import, &@import_callbacks[state]) if @import_callbacks[state]
50
+ def initialize
51
+ set_defaults!
54
52
  end
53
+ end
54
+
55
+ module Configurable
56
+ attr_writer :config
55
57
 
56
- def admin_visible_imports
57
- instance_exec(&@admin_visible_imports) if @admin_visible_imports
58
+ def config
59
+ @config ||= Configuration.new
58
60
  end
59
61
 
60
- def admin_can_destroy(import)
61
- instance_exec(import, &@admin_can_destroy) if @admin_can_destroy
62
+ def configure
63
+ yield(config)
62
64
  end
65
+ alias_method :setup, :configure
63
66
 
64
- def admin_extra_links(import)
65
- instance_exec(import, &@admin_extra_links) if @admin_extra_links
67
+ def reset_config!
68
+ @config = Configuration.new
66
69
  end
67
70
  end
68
71
  end
@@ -1,23 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "axlsx"
4
+ require "roo"
5
+ require "roo-xls"
6
+ require "slim"
7
+ require "state_machines-activerecord"
8
+ require "signum"
9
+ require "turbo-rails"
10
+ require "view_component"
11
+ require "with_advisory_lock"
12
+
3
13
  module Importo
4
14
  class Engine < ::Rails::Engine
5
15
  isolate_namespace Importo
6
16
 
7
- initializer 'importo.active_storage.attached' do
17
+ initializer "importo.active_storage.attached" do
8
18
  config.after_initialize do
9
19
  ActiveSupport.on_load(:active_record) do
10
20
  Importo::Import.include(ImportHelpers)
11
21
  end
12
22
  end
13
23
  end
14
-
15
- initializer 'importo.append_migrations' do |app|
16
- unless app.root.to_s.match?(root.to_s)
17
- config.paths['db/migrate'].expanded.each do |expanded_path|
18
- app.config.paths['db/migrate'] << expanded_path
19
- end
20
- end
21
- end
22
24
  end
23
25
  end
@@ -3,12 +3,12 @@
3
3
  module Importo
4
4
  class ImportColumn
5
5
  attr_accessor :proc, :options
6
- attr_writer :name, :hint, :explanation
6
+ attr_writer :name, :hint, :explanation, :value, :example
7
7
 
8
- def initialize(name, hint, explanation, options, &block)
8
+ def initialize(name: nil, **options, &block)
9
9
  @name = name
10
- @hint = hint
11
- @explanation = explanation
10
+ @hint = options[:hint]
11
+ @explanation = options[:explanation]
12
12
  @options = options || {}
13
13
  @proc = block
14
14
  end
@@ -33,11 +33,19 @@ module Importo
33
33
  end
34
34
 
35
35
  def hint
36
- I18n.t(".hint.#{options[:attribute]}", scope: [:importers, options[:scope]], default: '') if options[:attribute]
36
+ I18n.t(".hint.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
37
37
  end
38
38
 
39
39
  def explanation
40
- I18n.t(".explanation.#{options[:attribute]}", scope: [:importers, options[:scope]], default: '') if options[:attribute]
40
+ I18n.t(".explanation.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
41
+ end
42
+
43
+ def value
44
+ I18n.t(".value.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
45
+ end
46
+
47
+ def example
48
+ I18n.t(".example.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
41
49
  end
42
50
 
43
51
  ##
@@ -51,5 +59,9 @@ module Importo
51
59
  def collection
52
60
  options[:collection]
53
61
  end
62
+
63
+ def delay
64
+ options[:delay]
65
+ end
54
66
  end
55
67
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "axlsx"
4
+
5
+ module Importo
6
+ module TestHelpers
7
+ def simple_sheet(an_array, sheet_name: "Import")
8
+ xls = Axlsx::Package.new
9
+ workbook = xls.workbook
10
+ sheet = workbook.add_worksheet(name: sheet_name)
11
+
12
+ an_array.each do |a|
13
+ sheet.add_row a
14
+ end
15
+
16
+ xls.to_stream
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Importo
4
- VERSION = "2.0.5"
4
+ VERSION = "3.0.9"
5
5
  end
data/lib/importo.rb CHANGED
@@ -1,29 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'axlsx'
4
- require 'roo'
5
- require 'roo-xls'
6
- require 'slim'
7
- require 'state_machines-activerecord'
8
- # require 'active_storage/downloading'
9
-
10
- require_relative 'importo/engine'
11
- require_relative 'importo/acts_as_import_owner'
12
- require_relative 'importo/import_column'
13
- require_relative 'importo/import_helpers'
14
- require_relative 'importo/configuration'
3
+ require_relative "importo/engine"
4
+ require_relative "importo/acts_as_import_owner"
5
+ require_relative "importo/import_column"
6
+ require_relative "importo/import_helpers"
7
+ require_relative "importo/configuration"
15
8
 
16
9
  module Importo
10
+ extend Configurable
11
+
17
12
  class Error < StandardError; end
18
13
 
19
14
  class DuplicateRowError < Error; end
20
15
 
21
- class << self
22
- attr_reader :config
16
+ class RetryError < StandardError
17
+ attr_reader :delay
23
18
 
24
- def setup
25
- @config = Configuration.new
26
- yield config
19
+ def initialize(msg, delay)
20
+ super(msg)
21
+ @delay = delay
27
22
  end
28
23
  end
29
24
  end