Class: TabHashReader

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/tabreader/reader_hash.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, headers: nil) ⇒ TabHashReader

Returns a new instance of TabHashReader.

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/tabreader/reader_hash.rb', line 62

def initialize( data, headers: nil )
      raise ArgumentError.new( "Cannot parse nil as TAB" )  if data.nil?

      if data.is_a?( String )
        @input = data   # note: just needs each for each_line
      else  ## assume io
        @input = data
      end

      ## pass in headers as array e.g. ['A', 'B', 'C']
      @names = headers ? headers : nil
end

Class Method Details

.foreach(path, headers: nil, &block) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/tabreader/reader_hash.rb', line 31

def self.foreach( path, headers: nil, &block )
  tab = open( path, headers: headers)

  if block_given?
    begin
      tab.each( &block )
    ensure
      tab.close
    end
  else
    tab.to_enum    ## note: caller (responsible) must close file!!!
    ## remove version without block given - why? why not?
    ## use Tab.open().to_enum  or Tab.open().each
    ##   or Tab.new( File.new() ).to_enum or Tab.new( File.new() ).each ???
  end
end

.open(path, mode = nil, headers: nil, &block) ⇒ Object

rename path to filename or name - why? why not?



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/tabreader/reader_hash.rb', line 6

def self.open( path, mode=nil, headers: nil, &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' )
    tab = new(f, headers: headers )

    # handle blocks like Ruby's open()
    if block_given?
      begin
        block.call( tab )
      ensure
        tab.close
      end
    else
      tab
    end
end

.parse(data, headers: nil, &block) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/tabreader/reader_hash.rb', line 49

def self.parse( data, headers: nil, &block )
  tab = new( data, headers: headers )

  if block_given?
    tab.each( &block )  ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
  else  # slurp contents, if no block is given
    tab.read            ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
  end
end

.read(path, headers: nil) ⇒ Object



25
26
27
# File 'lib/tabreader/reader_hash.rb', line 25

def self.read( path, headers: nil )
    open( path, headers: headers ) { |tab| tab.read }
end

Instance Method Details

#closeObject



106
107
108
# File 'lib/tabreader/reader_hash.rb', line 106

def close
  @input.close   if @input.respond_to?(:close)   ## note: string needs no close
end

#each(&block) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/tabreader/reader_hash.rb', line 80

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?
    TabReader.parse( @input ) do |values|
       if @names.nil?    ## check for (first) headers row
         @names = values   ## store header row / a.k.a. field/column names
       else    ## "regular" record
         record = @names.zip( values ).to_h    ## todo/fix: check for more values than names/headers!!!
         block.call( record )
       end
    end
  else
    to_enum
  end
end

#readObject

method each



103
# File 'lib/tabreader/reader_hash.rb', line 103

def read() to_a; end