importo 2.0.5 → 3.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -5
- data/Rakefile +16 -17
- data/app/controllers/concerns/maintenance_standards.rb +1 -1
- data/app/controllers/importo/imports_controller.rb +15 -12
- data/app/helpers/importo/application_helper.rb +11 -11
- data/app/importers/concerns/exportable.rb +31 -24
- data/app/importers/concerns/importable.rb +144 -62
- data/app/importers/concerns/importer_dsl.rb +6 -14
- data/app/importers/concerns/original.rb +23 -23
- data/app/importers/concerns/result_feedback.rb +62 -44
- data/app/importers/concerns/revertable.rb +11 -12
- data/app/importers/importo/base_importer.rb +16 -4
- data/app/importers/importo/import_job_callback.rb +29 -0
- data/app/jobs/importo/import_job.rb +40 -0
- data/app/mailers/importo/application_mailer.rb +2 -2
- data/app/models/importo/import.rb +35 -8
- data/app/models/importo/result.rb +5 -0
- data/app/services/importo/import_service.rb +1 -3
- data/app/services/importo/revert_service.rb +1 -1
- data/app/tables/importo/imports_table.rb +13 -17
- data/app/tables/importo/mensa_imports_table.rb +35 -0
- data/app/views/importo/imports/index.html.slim +6 -2
- data/app/views/importo/imports/new.html.slim +30 -20
- data/config/locales/en.yml +21 -9
- data/config/locales/nl.yml +10 -4
- data/config/routes.rb +4 -4
- data/db/migrate/20180409151031_create_importo_import.rb +9 -9
- data/db/migrate/20180628175535_add_locale_importo_import.rb +1 -1
- data/db/migrate/20230510051447_remove_result_from_imports.rb +5 -0
- data/db/migrate/20230510083043_create_importo_results.rb +11 -0
- data/lib/generators/importo/importer_generator.rb +1 -1
- data/lib/generators/importo/install_generator.rb +7 -8
- data/lib/generators/importo/templates/importo.rb +11 -0
- data/lib/generators/satis/install_generator.rb +22 -0
- data/lib/generators/satis/tailwind_config_generator.rb +24 -0
- data/lib/generators/satis/templates/config/initializers/satis.rb +13 -0
- data/lib/importo/acts_as_import_owner.rb +1 -1
- data/lib/importo/configuration.rb +52 -49
- data/lib/importo/engine.rb +11 -9
- data/lib/importo/import_column.rb +18 -6
- data/lib/importo/test_helpers.rb +19 -0
- data/lib/importo/version.rb +1 -1
- data/lib/importo.rb +12 -17
- metadata +75 -24
- data/app/services/importo/callback_service.rb +0 -14
- data/lib/generators/templates/importo.rb +0 -21
- /data/lib/generators/{templates → importo/templates}/README +0 -0
- /data/lib/generators/{templates → importo/templates}/application_importer.rb +0 -0
- /data/lib/generators/{templates → importo/templates}/importer.rb +0 -0
@@ -1,24 +1,34 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
=
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
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
|
|
data/config/locales/en.yml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
en:
|
2
2
|
helpers:
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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:
|
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:
|
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:
|
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
|
-
|
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"
|
data/config/locales/nl.yml
CHANGED
@@ -6,23 +6,29 @@ nl:
|
|
6
6
|
explanation:
|
7
7
|
name: Uitleg
|
8
8
|
column: Kolom
|
9
|
-
|
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:
|
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:
|
29
|
+
success: "Import geplanned met id %{id}, je krijgt een email met de resultaten."
|
25
30
|
errors:
|
26
|
-
|
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
|
10
|
-
get
|
11
|
-
get
|
12
|
-
root to:
|
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
|
4
|
-
enable_extension
|
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
|
10
|
-
t.uuid
|
9
|
+
t.string :importo_ownable_type, null: false
|
10
|
+
t.uuid :importo_ownable_id, null: false
|
11
11
|
|
12
|
-
t.string
|
13
|
-
t.string
|
14
|
-
t.string
|
15
|
-
t.string
|
16
|
-
t.jsonb
|
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
|
@@ -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(
|
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
|
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(
|
8
|
+
source_root File.expand_path("../templates", __dir__)
|
10
9
|
|
11
|
-
desc
|
10
|
+
desc "Creates a Importo initializer and copy locale files to your application."
|
12
11
|
|
13
12
|
def copy_initializer
|
14
|
-
template
|
13
|
+
template "importo.rb", "config/initializers/importo.rb"
|
15
14
|
end
|
16
15
|
|
17
16
|
def copy_locale
|
18
|
-
copy_file
|
19
|
-
copy_file
|
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
|
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
|
@@ -1,68 +1,71 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Importo
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
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
|
48
|
-
|
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
|
53
|
-
|
50
|
+
def initialize
|
51
|
+
set_defaults!
|
54
52
|
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Configurable
|
56
|
+
attr_writer :config
|
55
57
|
|
56
|
-
def
|
57
|
-
|
58
|
+
def config
|
59
|
+
@config ||= Configuration.new
|
58
60
|
end
|
59
61
|
|
60
|
-
def
|
61
|
-
|
62
|
+
def configure
|
63
|
+
yield(config)
|
62
64
|
end
|
65
|
+
alias_method :setup, :configure
|
63
66
|
|
64
|
-
def
|
65
|
-
|
67
|
+
def reset_config!
|
68
|
+
@config = Configuration.new
|
66
69
|
end
|
67
70
|
end
|
68
71
|
end
|
data/lib/importo/engine.rb
CHANGED
@@ -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
|
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
|
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:
|
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:
|
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
|
data/lib/importo/version.rb
CHANGED
data/lib/importo.rb
CHANGED
@@ -1,29 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
22
|
-
attr_reader :
|
16
|
+
class RetryError < StandardError
|
17
|
+
attr_reader :delay
|
23
18
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
19
|
+
def initialize(msg, delay)
|
20
|
+
super(msg)
|
21
|
+
@delay = delay
|
27
22
|
end
|
28
23
|
end
|
29
24
|
end
|