diff --git a/app/views/admin/import.html.erb b/app/views/admin/import.html.erb index be191ef..c44af4a 100644 --- a/app/views/admin/import.html.erb +++ b/app/views/admin/import.html.erb @@ -1,11 +1,13 @@
- <%= raw(@active_admin_import_model.hint) %> + <%= raw(@active_admin_import_model.hint) %>
<%= semantic_form_for @active_admin_import_model, url: {action: :do_import}, html: {multipart: true} do |f| %> <%= f.inputs name: t("active_admin_import.details") do %> <%= f.input :file, as: :file %> + <%= f.input :col_sep, collection: [';', ','], include_blank: false, selected: ';' %> <% end %> + <%= f.actions do %> <%= f.action :submit, label: t("active_admin_import.import_btn"), button_html: {data: {disable_with: t("active_admin_import.import_btn_disabled")}} %> <% end %> -<% end %> \ No newline at end of file +<% end %> diff --git a/lib/active_admin_import/dsl.rb b/lib/active_admin_import/dsl.rb index 1d5303b..79bc144 100644 --- a/lib/active_admin_import/dsl.rb +++ b/lib/active_admin_import/dsl.rb @@ -92,11 +92,7 @@ def active_admin_import(options = {}, &block) else instance_exec result, options, &DEFAULT_RESULT_PROC end - rescue ActiveRecord::Import::MissingColumnError, - NoMethodError, - ActiveRecord::StatementInvalid, - CSV::MalformedCSVError, - ActiveAdminImport::Exception => e + rescue StandardError => e Rails.logger.error(I18n.t('active_admin_import.file_error', message: e.message)) Rails.logger.error(e.backtrace.join("\n")) flash[:error] = I18n.t('active_admin_import.file_error', message: e.message[0..200]) diff --git a/lib/active_admin_import/importer.rb b/lib/active_admin_import/importer.rb index 495d691..59e11ea 100644 --- a/lib/active_admin_import/importer.rb +++ b/lib/active_admin_import/importer.rb @@ -37,7 +37,7 @@ def file end def cycle(lines) - @csv_lines = CSV.parse(lines.join, @csv_options) + @csv_lines = lines import_result.add(batch_import, lines.count) end @@ -113,17 +113,20 @@ def header_index(header_key) def process_file lines = [] batch_size = options[:batch_size].to_i - File.open(file.path) do |f| - # capture headers if not exist - prepare_headers { CSV.parse(f.readline, @csv_options).first } - f.each_line do |line| - lines << line if line.present? - if lines.size == batch_size || f.eof? - cycle(lines) - lines = [] - end + + csv = CSV.read(file.path, @csv_options) + + prepare_headers { csv.shift } + + csv.each do |line| + lines << line + + if lines.size == batch_size + cycle(lines) + lines = [] end end + cycle(lines) unless lines.blank? end @@ -139,12 +142,21 @@ def run_callback(name) end def batch_import + @resource.respond_to?(:transaction) ? batch_improt_with_transaction : batch_import_without_transaction + end + + def batch_import_without_transaction + run_callback(:before_batch_import) + batch_result = resource.import(headers.values, csv_lines, import_options) + raise ActiveRecord::Rollback if Object.const_defined?('ActiveRecord::Rollback') && import_options[:batch_transaction] && batch_result.failed_instances.any? + run_callback(:after_batch_import) + batch_result + end + + def batch_improt_with_transaction batch_result = nil @resource.transaction do - run_callback(:before_batch_import) - batch_result = resource.import(headers.values, csv_lines, import_options) - raise ActiveRecord::Rollback if import_options[:batch_transaction] && batch_result.failed_instances.any? - run_callback(:after_batch_import) + batch_result = batch_import_without_transaction end batch_result end @@ -163,6 +175,7 @@ def detect_csv_options else options[:csv_options] || {} end.reject { |_, value| value.nil? || value == "" } + @csv_options[:col_sep] = model.col_sep if model.respond_to?(:col_sep) end end end diff --git a/lib/active_admin_import/model.rb b/lib/active_admin_import/model.rb index 11db86e..c8f0e6d 100644 --- a/lib/active_admin_import/model.rb +++ b/lib/active_admin_import/model.rb @@ -65,7 +65,8 @@ def default_attributes csv_headers: [], file: nil, force_encoding: 'UTF-8', - hint: '' + hint: '', + col_sep: ';' } end