class CSVSafe

Decorate the built in CSV library Override << to sanitize incoming rows Override initialize to add a converter that will sanitize fields being read

Public Class Methods

new(data, options = {}) click to toggle source
Calls superclass method
# File lib/csv-safe.rb, line 7
def initialize(data, options = {})
  options[:converters] = [] if options[:converters].nil?
  options[:converters] << lambda(&method(:sanitize_field))
  super
end

Public Instance Methods

<<(row) click to toggle source
Calls superclass method
# File lib/csv-safe.rb, line 13
def <<(row)
  super(sanitize_row(row))
end
Also aliased as: add_row, puts
add_row(row)
Alias for: <<
puts(row)
Alias for: <<

Private Instance Methods

prefix(field) click to toggle source
# File lib/csv-safe.rb, line 27
def prefix(field)
  encoded = field.encode(CSV::ConverterEncoding)
  "'" + encoded
rescue StandardError
  "'" + field
end
prefix_if_necessary(field) click to toggle source
# File lib/csv-safe.rb, line 34
def prefix_if_necessary(field)
  as_string = field.to_s
  if starts_with_special_character?(as_string)
    prefix(as_string)
  else
    field
  end
end
sanitize_field(field) click to toggle source
# File lib/csv-safe.rb, line 43
def sanitize_field(field)
  if field.nil? || field.is_a?(Numeric)
    field
  else
    prefix_if_necessary(field)
  end
end
sanitize_row(row) click to toggle source
# File lib/csv-safe.rb, line 51
def sanitize_row(row)
  case row
  when self.class::Row
    then row.fields.map { |field| sanitize_field(field) }
  when Hash
    then @headers.map { |header| sanitize_field(row[header]) }
  else
    row.map { |field| sanitize_field(field) }
  end
end
starts_with_special_character?(str) click to toggle source

TODO: performance test if i'm adding too many method calls to hot code

# File lib/csv-safe.rb, line 23
def starts_with_special_character?(str)
  %w[- = + @].include?(str[0])
end