Class: RowBoat::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/row_boat/base.rb

Constant Summary collapse

InvalidColumnMapping =
Class.new(StandardError)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(csv_source) ⇒ Base

This method is abstract.

Override this method if you need additional arguments to process your CSV (like defaults).

Makes a new instance with the given csv_source.

Examples:

def initialize(csv_source, default_name)
  super(csv_source)
  @default_name = default_name
end


36
37
38
# File 'lib/row_boat/base.rb', line 36

def initialize(csv_source)
  @csv_source = csv_source
end

Instance Attribute Details

#csv_sourceObject (readonly)

Returns the value of attribute csv_source.



11
12
13
# File 'lib/row_boat/base.rb', line 11

def csv_source
  @csv_source
end

Class Method Details

.import(csv_source) ⇒ Hash

Imports database records from the given CSV-like object.

Parameters:

  • csv_source (String, #read)

    a CSV-like object that SmarterCSV can read.

Returns:

  • (Hash)

    a hash with :invalid_records, :total_inserts, :inserted_ids, and :skipped_rows.

See Also:



22
23
24
# File 'lib/row_boat/base.rb', line 22

def import(*, &)
  new(*, &).import
end

Instance Method Details

#column_mappingObject

This method is abstract.
Note:

You must implement this method.

Override with a hash that maps CSV column names to their preferred names.

Oftentimes these are the names of the attributes on the model class from {#import_into}.

Examples:

def column_mapping
  {
    prdct_name: :name,
    price: :price,
    sl_exp: :sale_expires_at
  }
end

Raises:

  • (NotImplementedError)

See Also:



89
90
91
# File 'lib/row_boat/base.rb', line 89

def column_mapping
  raise NotImplementedError, not_implemented_error_message(__method__)
end

#csv_value_convertersObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/row_boat/base.rb', line 216

def csv_value_converters
  value_converters.each_with_object({}) do |(key, potential_converter), converters_hash|
    case potential_converter
    when Proc
      converters_hash[key] = ::RowBoat::ValueConverter.new(&potential_converter)
    when Symbol
      converters_hash[key] = ::RowBoat::ValueConverter.new { |value| public_send(potential_converter, value) }
    when nil
      next
    else
      converters_hash[key] = potential_converter
    end
  end
end

#default_optionsHash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Do not override.

Default options provided by RowBoat for CSV parsing and importing.

Returns:

  • (Hash)

    a hash of configuration options.



156
157
158
159
160
161
162
163
164
# File 'lib/row_boat/base.rb', line 156

def default_options
  {
    chunk_size: 500,
    recursive: false,
    validate: true,
    value_converters: csv_value_converters,
    wrap_in_transaction: true
  }.merge(column_mapping_options)
end

#handle_failed_row(row) ⇒ Object

This method is abstract.
Note:

row here is actually an instance of the class returned in #import_into

Override this method to do some work with a row that has failed to import.

See Also:



178
179
180
# File 'lib/row_boat/base.rb', line 178

def handle_failed_row(row)
  row
end

#handle_failed_rows(rows) ⇒ Object

This method is abstract.
Note:

If you override this method and #handle_failed_row, be sure to call super.

Override this method to do some work will all of the rows that failed to import.



187
188
189
# File 'lib/row_boat/base.rb', line 187

def handle_failed_rows(rows)
  rows.each { |row| handle_failed_row(row) }
end

#importHash

Parses the csv and inserts/updates the database. You probably won’t call this method directly, instead you would call import.

Returns:

  • (Hash)

    a hash with :invalid_records, :total_inserts, :inserted_ids, and :skipped_rows.



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/row_boat/base.rb', line 44

def import
  import_results = []

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

  process_import_results(import_results).tap do |total_results|
    handle_failed_rows(total_results[:invalid_records])
  end
end

#import_intoObject

This method is abstract.
Note:

You must implement this method.

Override with the ActiveRecord class that the CSV should be imported into.

Examples:

def import_into
  Product
end

Raises:

  • (NotImplementedError)


68
69
70
# File 'lib/row_boat/base.rb', line 68

def import_into
  raise NotImplementedError, not_implemented_error_message(__method__)
end

#import_rows(rows) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



110
111
112
113
114
# File 'lib/row_boat/base.rb', line 110

def import_rows(rows)
  import_options = ::RowBoat::Helpers.extract_import_options(merged_options)
  preprocessed_rows = preprocess_rows(rows)
  import_into.import(preprocessed_rows, import_options)
end

#merged_optionsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



167
168
169
# File 'lib/row_boat/base.rb', line 167

def merged_options
  default_options.merge(options)
end

#optionsHash

This method is abstract.
Note:

If you want to use the :value_converters option provided by SmarterCSV just override #value_converters.

Override this method to specify CSV parsing and importing options.

All SmarterCSV and activerecord-import options can be listed here along with
+:wrap_in_transaction+. The defaults provided by RowBoat can be found in {#default_options}

Returns:

  • (Hash)

    a hash of configuration options.

See Also:



145
146
147
# File 'lib/row_boat/base.rb', line 145

def options
  {}
end

#preprocess_row(row) ⇒ Hash, NilClass

This method is abstract.
Note:

If you only need to manipulate one attribute (ie parse a date from a string, etc), then you should probably use #value_converters

Override this method if you need to do some work on the row before the record is

inserted/updated or want to skip the row in the import. Simply return +nil+ to skip the row.

Returns:

  • (Hash, NilClass)

    a hash of attributes, nil, or even and instance of the class returned in #import_into.

See Also:



105
106
107
# File 'lib/row_boat/base.rb', line 105

def preprocess_row(row)
  row
end

#preprocess_rows(rows) ⇒ Object

This method is abstract.
Note:

If you want to filter out a row, you can just return nil from #preprocess_row.

Override this method if you need to do something with a chunk of rows.

See Also:



123
124
125
126
127
128
129
# File 'lib/row_boat/base.rb', line 123

def preprocess_rows(rows)
  rows.each_with_object([]) do |row, preprocessed_rows|
    increment_row_number
    preprocessed_row = preprocess_row(row)
    preprocessed_row ? preprocessed_rows << preprocessed_row : add_skipped_row(row)
  end
end

#rollback_transaction?Boolean

This method is abstract.
Note:

Only works if the ‘wrap_in_transaction` option is `true` (which is the default)

Implement this method if you’d like to rollback the transaction

after it otherwise has completed.

Returns:

  • (Boolean)


240
241
242
# File 'lib/row_boat/base.rb', line 240

def rollback_transaction?
  false
end

#value_convertersObject

This method is abstract.

Override this method to specify how to translate values from the CSV

into ruby objects.

You can provide an object that implements +convert+, a proc or lambda, or the
the name of a method as a Symbol

Examples:

def value_converters
  {
    name: -> (value) { value.titleize }
    price: :convert_price,
    expires_at: CustomDateConverter
  }
end

def convert_price(value)
  value || 0
end


211
212
213
# File 'lib/row_boat/base.rb', line 211

def value_converters
  {}
end