Sha256: 298c31f40c63df9bf4c1e33ccccba7d5f4ff46dccd4f0be7fafd8f3f22358538

Contents?: true

Size: 1.97 KB

Versions: 1

Compression:

Stored size: 1.97 KB

Contents

# frozen_string_literal: true

require "active_record"
require "activerecord-import"
require "smarter_csv"

module RowBoat
  class Base
    attr_reader :csv_source

    class << self
      def import(*args, &block)
        new(*args, &block).import
      end
    end

    def initialize(csv_source)
      @csv_source = csv_source
    end

    def import
      import_results = []

      transaction_if_needed do
        parse_rows do |rows|
          import_results << import_rows(rows)
        end
      end

      import_results.each_with_object(invalid_records: [], total_inserted: 0, inserted_ids: []) do |import_result, total_results|
        total_results[:invalid_records] += import_result.failed_instances
        total_results[:total_inserted] += import_result.num_inserts
        total_results[:inserted_ids] += import_result.ids
      end
    end

    def import_into
      raise NotImplementedError, not_implemented_error_message(__method__)
    end

    def column_mapping
      raise NotImplementedError, not_implemented_error_message(__method__)
    end

    def preprocess_row(row)
      row
    end

    def import_rows(rows)
      import_options = ::RowBoat::Helpers.extract_import_options(options)
      preprocessed_rows = rows.map { |row| preprocess_row(row) }
      import_into.import(preprocessed_rows, import_options)
    end

    def options
      {
        chunk_size: 500,
        key_mapping: column_mapping,
        recursive: true,
        remove_unmapped_keys: true,
        validate: true,
        wrap_in_transaction: true
      }
    end

    private

    def not_implemented_error_message(method_name)
      "Subclasses of #{self.class.name} must implement `#{method_name}`"
    end

    def parse_rows(&block)
      csv_options = ::RowBoat::Helpers.extract_csv_options(options)
      ::SmarterCSV.process(csv_source, csv_options, &block)
    end

    def transaction_if_needed(&block)
      options[:wrap_in_transaction] ? import_into.transaction(&block) : yield
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
row_boat-0.1.0.alpha.2 lib/row_boat/base.rb