class RailsAdminImport::Importer

Attributes

import_model[R]
params[R]
results[R]

Public Class Methods

new(import_model, params) click to toggle source
# File lib/rails_admin_import/importer.rb, line 5
def initialize(import_model, params)
  @import_model = import_model
  @params = params
end

Public Instance Methods

import(records) click to toggle source
# File lib/rails_admin_import/importer.rb, line 15
def import(records)
  begin
    init_results

    if records.count > RailsAdminImport.config.line_item_limit
      return results = {
        success: [],
        error: [I18n.t('admin.import.import_error.line_item_limit', limit: RailsAdminImport.config.line_item_limit)]
      }
    end

    perform_global_callback(:before_import)

    with_transaction do
      records.each do |record|
        catch :skip do
          import_record(record)
        end
      end

      rollback_if_error
    end

    perform_global_callback(:after_import)
  rescue Exception => e
    report_general_error("#{e} (#{e.backtrace.first})")
  end

  format_results
end

Private Instance Methods

extract_mapping(value, mapping_key) click to toggle source
# File lib/rails_admin_import/importer.rb, line 247
def extract_mapping(value, mapping_key)
  if value.is_a? Hash
    value[mapping_key]
  else
    value
  end
end
find_or_create_object(record, update) click to toggle source
# File lib/rails_admin_import/importer.rb, line 192
def find_or_create_object(record, update)
  model = import_model.model
  object = if update.present?
             query = update.each_with_object({}) do
               |field, query| query[field] = record[field]
             end
             model.where(query).first
           end

  if object.nil?
    object = model.new
  end

  perform_model_callback(object, :before_import_attributes, record)

  field_names = import_model.model_fields.map(&:name)
  new_attrs = record.select do |field_name, value|
    field_names.include?(field_name) && (!value.blank? || value == false)
  end

  if object.new_record?
    object.attributes = new_attrs
  else
    object.attributes = new_attrs.except(update.map(&:to_sym))
  end
  object
end
format_result_message(type, array) click to toggle source
# File lib/rails_admin_import/importer.rb, line 157
def format_result_message(type, array)
  result_count = "#{array.size} #{import_model.display_name.pluralize(array.size)}"
  I18n.t("admin.flash.#{type}",
         name: result_count,
           action: I18n.t("admin.actions.import.done"))
end
format_results() click to toggle source
# File lib/rails_admin_import/importer.rb, line 144
def format_results
  imported = results[:success]
  not_imported = results[:error]
  unless imported.empty?
    results[:success_message] = format_result_message("successful", imported)
  end
  unless not_imported.empty?
    results[:error_message] = format_result_message("error", not_imported)
  end

  results
end
import_many_association_data(object, record) click to toggle source
# File lib/rails_admin_import/importer.rb, line 231
def import_many_association_data(object, record)
  import_model.many_association_fields.each do |field|
    if record.has_key? field.name
      mapping_key = params[:associations][field.name]
      values = record[field.name].reject { |value| value.blank? }.map { |value|
        extract_mapping(value, mapping_key)
      }

      if !values.empty?
        associated = values.map { |value| import_model.associated_object(field, mapping_key, value) }
        object.send "#{field.name}=", associated
      end
    end
  end
end
import_record(record) click to toggle source
# File lib/rails_admin_import/importer.rb, line 72
def import_record(record)
  if params["file"] && RailsAdminImport.config.pass_filename
    record.merge!({:filename_importer => params[:file].original_filename})
  end

  perform_model_callback(import_model.model, :before_import_find, record)

  if update_lookup && !(update_lookup - record.keys).empty?
    raise UpdateLookupError, I18n.t("admin.import.missing_update_lookup")
  end

  object = find_or_create_object(record, update_lookup)
  return if object.nil?
  action = object.new_record? ? :create : :update

  begin
    perform_model_callback(object, :before_import_associations, record)
    import_single_association_data(object, record)
    import_many_association_data(object, record)
  rescue AssociationNotFound => e
    error = I18n.t("admin.import.association_not_found", :error => e.to_s)
    report_error(object, action, error)
    perform_model_callback(object, :after_import_association_error, record)
    return
  end

  perform_model_callback(object, :before_import_save, record)

  if object.save
    report_success(object, action)
    perform_model_callback(object, :after_import_save, record)
  else
    report_error(object, action, object.errors.full_messages.join(", "))
    perform_model_callback(object, :after_import_error, record)
  end
end
import_single_association_data(object, record) click to toggle source
# File lib/rails_admin_import/importer.rb, line 220
def import_single_association_data(object, record)
  import_model.single_association_fields.each do |field|
    mapping_key = params[:associations][field.name]
    value = extract_mapping(record[field.name], mapping_key)

    if !value.blank?
      object.send "#{field.name}=", import_model.associated_object(field, mapping_key, value)
    end
  end
end
init_results() click to toggle source
# File lib/rails_admin_import/importer.rb, line 48
def init_results
  @results = { :success => [], :error => [] }
end
logger() click to toggle source
# File lib/rails_admin_import/importer.rb, line 117
def logger
  @logger ||= ImportLogger.new
end
perform_global_callback(method_name) click to toggle source
# File lib/rails_admin_import/importer.rb, line 187
def perform_global_callback(method_name)
  object = import_model.model
  object.send(method_name) if object.respond_to?(method_name)
end
perform_model_callback(object, method_name, record) click to toggle source
# File lib/rails_admin_import/importer.rb, line 164
def perform_model_callback(object, method_name, record)
  if object.respond_to?(method_name)
    # Compatibility: Old import hook took 2 arguments.
    # Warn and call with a blank hash as 2nd argument.
    if object.method(method_name).arity == 2
      report_old_import_hook(method_name)
      object.send(method_name, record, {})
    else
      object.send(method_name, record)
    end
  end
end
report_error(object, action, error) click to toggle source
# File lib/rails_admin_import/importer.rb, line 129
def report_error(object, action, error)
  object_label = import_model.label_for_model(object)
  message = I18n.t("admin.import.import_error.#{action}",
                   :name => object_label,
                   :error => error)
  logger.info "#{Time.now}: #{message}"
  results[:error] << message
end
report_general_error(error) click to toggle source
# File lib/rails_admin_import/importer.rb, line 138
def report_general_error(error)
  message = I18n.t("admin.import.import_error.general", :error => error)
  logger.info "#{Time.now}: #{message}"
  results[:error] << message
end
report_old_import_hook(method_name) click to toggle source
# File lib/rails_admin_import/importer.rb, line 177
def report_old_import_hook(method_name)
  unless @old_import_hook_reported
    error = I18n.t("admin.import.import_error.old_import_hook",
                   model: import_model.display_name,
                   method: method_name)
    report_general_error(error)
    @old_import_hook_reported = true
  end
end
report_success(object, action) click to toggle source
# File lib/rails_admin_import/importer.rb, line 121
def report_success(object, action)
  object_label = import_model.label_for_model(object)
  message = I18n.t("admin.import.import_success.#{action}",
                   :name => object_label)
  logger.info "#{Time.now}: #{message}"
  results[:success] << message
end
rollback_if_error() click to toggle source
# File lib/rails_admin_import/importer.rb, line 62
def rollback_if_error
  if RailsAdminImport.config.rollback_on_error &&
    defined?(ActiveRecord) &&
    !results[:error].empty?

    results[:success] = []
    raise ActiveRecord::Rollback
  end
end
update_lookup() click to toggle source
# File lib/rails_admin_import/importer.rb, line 109
def update_lookup
  @update_lookup ||= if params[:update_if_exists] == "1"
                       params[:update_lookup].map(&:to_sym)
                     end
end
with_transaction(&block) click to toggle source
# File lib/rails_admin_import/importer.rb, line 52
def with_transaction(&block)
  if RailsAdminImport.config.rollback_on_error &&
    defined?(ActiveRecord)

    ActiveRecord::Base.transaction &block
  else
    block.call
  end
end