class CsvHash

Constants

Converter
DEFAULT

pre-define CsvReader (built-in) formats/dialect

EXCEL
FIXED
JSON
MYSQL
NUMERIC
POSTGRES
POSTGRES_TEXT
Parser

add convenience shortcuts / aliases for CsvReader support classes

ParserFixed
ParserJson
ParserYaml
RFC4180
STRICT
TAB
TABLE
YAML

Public Class Methods

default() click to toggle source
# File lib/csvreader/base.rb, line 186
def self.default()         DEFAULT;         end
excel() click to toggle source
# File lib/csvreader/base.rb, line 192
def self.excel()           EXCEL;           end
f() click to toggle source
# File lib/csvreader/base.rb, line 203
def self.f()               fixed;           end
fix() click to toggle source
# File lib/csvreader/base.rb, line 202
def self.fix()             fixed;           end
fixed() click to toggle source
# File lib/csvreader/base.rb, line 201
def self.fixed()           FIXED;           end
foreach( path, headers: nil, sep: nil, converters: nil, header_converters: nil, parser: nil, **kwargs, &block ) click to toggle source
# File lib/csvreader/reader_hash.rb, line 59
def self.foreach( path, headers: nil,
                        sep: nil,
                        converters: nil,
                        header_converters: nil,
                        parser: nil, **kwargs, &block )
  csv = open( path,
              headers: headers,
              sep: sep,
              converters: converters,
              header_converters: header_converters,
              parser: parser,
              **kwargs )

  if block_given?
    begin
      csv.each( &block )
    ensure
      csv.close
    end
  else
    csv.to_enum    ## note: caller (responsible) must close file!!!
    ## remove version without block given - why? why not?
    ## use Csv.open().to_enum  or Csv.open().each
    ##   or Csv.new( File.new() ).to_enum or Csv.new( File.new() ).each ???
  end
end
j() click to toggle source
# File lib/csvreader/base.rb, line 206
def self.j()               json;            end
json() click to toggle source
# File lib/csvreader/base.rb, line 205
def self.json()            JSON;            end
mysql() click to toggle source
# File lib/csvreader/base.rb, line 193
def self.mysql()           MYSQL;           end
n() click to toggle source
# File lib/csvreader/base.rb, line 189
def self.n()               numeric;         end
new( str_or_readable, headers: nil, sep: nil, converters: nil, header_converters: nil, parser: nil, **kwargs ) click to toggle source
# File lib/csvreader/reader_hash.rb, line 110
def initialize( str_or_readable, headers: nil, sep: nil,
                      converters: nil,
                      header_converters: nil,
                      parser: nil,
                      **kwargs )
      raise ArgumentError.new( "Cannot parse nil as CSV" )  if str_or_readable.nil?
      ## todo: use (why? why not) - raise ArgumentError, "Cannot parse nil as CSV"     if data.nil?

      # create the IO object we will read from
      @io = str_or_readable.is_a?(String) ? StringIO.new(str_or_readable) : str_or_readable

      ## pass in headers as array e.g. ['A', 'B', 'C']
      ##  double check: run header_converters on passed in headers?
      ##    for now - do NOT auto-convert passed in headers - keep them as-is (1:1)
      @names = headers ? headers : nil

      @sep    = sep
      @kwargs = kwargs

      @converters        = Converter.create_converters( converters )
      @header_converters = Converter.create_header_converters( header_converters )

      @parser = parser.nil? ? Parser::DEFAULT : parser
end
num() click to toggle source
# File lib/csvreader/base.rb, line 188
def self.num()             numeric;         end
numeric() click to toggle source
# File lib/csvreader/base.rb, line 187
def self.numeric()         NUMERIC;         end
open( path, mode=nil, headers: nil, sep: nil, converters: nil, header_converters: nil, parser: nil, **kwargs, &block ) click to toggle source
# File lib/csvreader/reader_hash.rb, line 15
def self.open( path, mode=nil,
               headers: nil,
               sep: nil,
               converters: nil,
               header_converters: nil,
               parser: nil, **kwargs, &block )   ## rename path to filename or name - why? why not?

    ## note: default mode (if nil/not passed in) to 'r:bom|utf-8'
    f = File.open( path, mode ? mode : 'r:bom|utf-8' )
    csv = new(f, headers: headers,
                 sep: sep,
                 converters: converters,
                 header_converters: header_converters,
                 parser: parser, **kwargs )

    # handle blocks like Ruby's open(), not like the (old old) CSV library
    if block_given?
      begin
        block.call( csv )
      ensure
        csv.close
      end
    else
      csv
    end
end
parse( str_or_readable, headers: nil, sep: nil, converters: nil, header_converters: nil, parser: nil, **kwargs, &block ) click to toggle source
# File lib/csvreader/reader_hash.rb, line 87
def self.parse( str_or_readable, headers: nil,
                      sep: nil,
                      converters: nil,
                      header_converters: nil,
                      parser: nil, **kwargs, &block )
  csv = new( str_or_readable,
             headers: headers,
             sep: sep,
             converters: converters,
             header_converters: header_converters,
             parser: parser, **kwargs )

  if block_given?
    csv.each( &block )  ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
  else  # slurp contents, if no block is given
    csv.read            ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
  end
end
postgres() click to toggle source
# File lib/csvreader/base.rb, line 195
def self.postgres()        postgresql;      end
postgres_text() click to toggle source
# File lib/csvreader/base.rb, line 197
def self.postgres_text()   postgresql_text; end
postgresql() click to toggle source
# File lib/csvreader/base.rb, line 194
def self.postgresql()      POSTGRESQL;      end
postgresql_text() click to toggle source
# File lib/csvreader/base.rb, line 196
def self.postgresql_text() POSTGRESQL_TEXT; end
read( path, headers: nil, sep: nil, converters: nil, header_converters: nil, parser: nil, **kwargs ) click to toggle source
# File lib/csvreader/reader_hash.rb, line 43
def self.read( path, headers: nil,
                     sep: nil,
                     converters: nil,
                     header_converters: nil,
                     parser: nil,
                     **kwargs )
    open( path,
          headers: headers,
          sep: sep,
          converters: converters,
          header_converters: header_converters,
          parser: parser, **kwargs ) { |csv| csv.read }
end
rfc4180() click to toggle source
# File lib/csvreader/base.rb, line 191
def self.rfc4180()         RFC4180;         end
strict() click to toggle source
# File lib/csvreader/base.rb, line 190
def self.strict()          STRICT;          end
tab() click to toggle source
# File lib/csvreader/base.rb, line 199
def self.tab()             TAB;             end
table() click to toggle source
# File lib/csvreader/base.rb, line 200
def self.table()           TABLE;           end
y() click to toggle source
# File lib/csvreader/base.rb, line 208
def self.y()               yaml;            end
yaml() click to toggle source
# File lib/csvreader/base.rb, line 207
def self.yaml()            YAML;            end

Public Instance Methods

each( &block ) click to toggle source
# File lib/csvreader/reader_hash.rb, line 154
def each( &block )

  ## todo/fix:
  ##   add case for headers/names.size != values.size
  ##   - add rest option? for if less headers than values (see python csv.DictReader - why? why not?)
  ##
  ##   handle case with duplicate and empty header names etc.


  if block_given?
    kwargs = {}
    ## note: only add separator if present/defined (not nil)
    ##  todo/fix: change sep keyword to "known" classes!!!!
    kwargs[:sep] = @sep    if @sep && @parser.respond_to?( :'sep=' )

    kwargs[:width] = @kwargs[:width]    if @parser.is_a?( ParserFixed )


    @parser.parse( @io, kwargs ) do |raw_values|     # sep: sep
       if @names.nil?    ## check for (first) headers row
         if @header_converters.empty?
           @names = raw_values   ## store header row / a.k.a. field/column names
         else
           values = []
           raw_values.each_with_index do |value,i|
             values << @header_converters.convert( value, i )
           end
           @names = values
         end
       else    ## "regular" record
         raw_record = @names.zip( raw_values ).to_h    ## todo/fix: check for more values than names/headers!!!
         if @converters.empty?
           block.call( raw_record )
         else
           ## add "post"-processing with converters pipeline
           ##   that is, convert all strings to integer, float, date, ... if wanted
           record = {}
           raw_record.each do | key, value |
             record[ key ] = @converters.convert( value, key )
           end
           block.call( record )
         end
       end
    end
  else
    to_enum
  end
end
read() click to toggle source
# File lib/csvreader/reader_hash.rb, line 203
def read() to_a; end