class ActiveAdminImport::Importer

Constants

OPTIONS

Attributes

csv_lines[RW]
headers[RW]
model[R]
options[R]
resource[R]
result[R]

Public Class Methods

new(resource, model, options) click to toggle source
# File lib/active_admin_import/importer.rb, line 24
def initialize(resource, model, options)
  @resource = resource
  @model = model
  @headers = model.respond_to?(:csv_headers) ? model.csv_headers : []
  assign_options(options)
end

Public Instance Methods

batch_replace(header_key, options) click to toggle source
# File lib/active_admin_import/importer.rb, line 64
def batch_replace(header_key, options)
  index = header_index(header_key)
  csv_lines.map! do |line|
    from = line[index]
    line[index] = options[from] if options.key?(from)
    line
  end
end
batch_slice_columns(slice_columns) click to toggle source

Use this method when CSV file contains unnecessary columns

Example:

ActiveAdmin.register Post

active_admin_import before_batch_import: lambda { |importer|
                      importer.batch_slice_columns(['name', 'birthday'])
                    }

end

# File lib/active_admin_import/importer.rb, line 83
def batch_slice_columns(slice_columns)
  # Only set @use_indexes for the first batch so that @use_indexes are in correct
  # position for subsequent batches
  unless defined?(@use_indexes)
    @use_indexes = []
    headers.values.each_with_index do |val, index|
      @use_indexes << index if val.in?(slice_columns)
    end
    return csv_lines if @use_indexes.empty?

    # slice CSV headers
    @headers = headers.to_a.values_at(*@use_indexes).to_h
  end

  # slice CSV values
  csv_lines.map! do |line|
    line.values_at(*@use_indexes)
  end
end
cycle(lines) click to toggle source
# File lib/active_admin_import/importer.rb, line 39
def cycle(lines)
  @csv_lines = CSV.parse(lines.join, @csv_options)
  import_result.add(batch_import, lines.count)
end
file() click to toggle source
# File lib/active_admin_import/importer.rb, line 35
def file
  @model.file
end
header_index(header_key) click to toggle source
# File lib/active_admin_import/importer.rb, line 107
def header_index(header_key)
  headers.values.index(header_key)
end
import() click to toggle source
# File lib/active_admin_import/importer.rb, line 44
def import
  run_callback(:before_import)
  process_file
  run_callback(:after_import)
  import_result
end
import_options() click to toggle source
# File lib/active_admin_import/importer.rb, line 51
def import_options
  @import_options ||= options.slice(
    :validate,
    :validate_uniqueness,
    :on_duplicate_key_update,
    :on_duplicate_key_ignore,
    :ignore,
    :timestamps,
    :batch_transaction,
    :batch_size
  )
end
import_result() click to toggle source
# File lib/active_admin_import/importer.rb, line 31
def import_result
  @import_result ||= ImportResult.new
end
values_at(header_key) click to toggle source
# File lib/active_admin_import/importer.rb, line 103
def values_at(header_key)
  csv_lines.collect { |line| line[header_index(header_key)] }.uniq
end

Protected Instance Methods

assign_options(options) click to toggle source
# File lib/active_admin_import/importer.rb, line 152
def assign_options(options)
  @options = {
    batch_size: 1000,
    validate_uniqueness: true
  }.merge(options.slice(*OPTIONS))
  detect_csv_options
end
batch_import() click to toggle source
# File lib/active_admin_import/importer.rb, line 141
def batch_import
  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)
  end
  batch_result
end
detect_csv_options() click to toggle source
# File lib/active_admin_import/importer.rb, line 160
def detect_csv_options
  @csv_options = if model.respond_to?(:csv_options)
                   model.csv_options
                 else
                   options[:csv_options] || {}
                 end.reject { |_, value| value.nil? || value == "" }
end
prepare_headers() { || ... } click to toggle source
# File lib/active_admin_import/importer.rb, line 130
def prepare_headers
  headers = self.headers.present? ? self.headers.map(&:to_s) : yield
  @headers = Hash[headers.zip(headers.map { |el| el.underscore.gsub(/\s+/, '_') })].with_indifferent_access
  @headers.merge!(options[:headers_rewrites].symbolize_keys.slice(*@headers.symbolize_keys.keys))
  @headers
end
process_file() click to toggle source
# File lib/active_admin_import/importer.rb, line 113
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
    end
  end
  cycle(lines) unless lines.blank?
end
run_callback(name) click to toggle source
# File lib/active_admin_import/importer.rb, line 137
def run_callback(name)
  options[name].call(self) if options[name].is_a?(Proc)
end