csvrecord 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea4f015ade2a8b105eb89aec99e4a9bd7f5be01c
4
- data.tar.gz: 2738c2e3655a29e3a626eb7aee228d9b7275a3bd
3
+ metadata.gz: f60b9d15d91c6d20b625bb343d895ad750f43a81
4
+ data.tar.gz: 5510e7921a509fe40906de7f533f185bf244e8bd
5
5
  SHA512:
6
- metadata.gz: '0290ce3db55dfa7e3e24f00db9aa4c918be94b04c408415844015d09fa8f0eabee4f8989ac7f9dfb7fc917dbd428727da25ee1d84200057b5bbe6c9add3e18ce'
7
- data.tar.gz: 6c47502227af693814a99f7d34bd9fede8afadc556d1797c1cf365437e7491312bd7d1037c23eb0923775884bb0ed5e55ac5a62642d940810db7fa9bdb3e4a5d
6
+ metadata.gz: 9853722319a53c73469238440eb2c249cd8c3829711acbd35efc60996316f8d8e763d5f61decdc4e3186baebf13536c46c72217fd92f08e6d675b7a6c088568b
7
+ data.tar.gz: bd2922bf8c44a458abe70b5dceee9b405904f878eacdaf34a1454a2313c43517329d31841c2bc4faca5c6d3492220d9c5c3091115171046c087a2889a4415339
data/Manifest.txt CHANGED
@@ -6,7 +6,12 @@ Rakefile
6
6
  lib/csvrecord.rb
7
7
  lib/csvrecord/base.rb
8
8
  lib/csvrecord/builder.rb
9
+ lib/csvrecord/reader.rb
9
10
  lib/csvrecord/version.rb
10
11
  test/data/beer.csv
12
+ test/data/beer11.csv
11
13
  test/helper.rb
12
- test/test_beer.rb
14
+ test/test_reader.rb
15
+ test/test_record.rb
16
+ test/test_record_auto.rb
17
+ test/test_version.rb
data/README.md CHANGED
@@ -74,11 +74,18 @@ pretty prints (pp):
74
74
  Or loop over the records. Example:
75
75
 
76
76
  ``` ruby
77
- Beer.read( data ).each do |rec|
77
+ Beer.read( 'beer.csv' ).each do |rec|
78
+ puts "#{rec.name} (#{rec.abv}%) by #{rec.brewery}, #{rec.city}"
79
+ end
80
+
81
+ # -or-
82
+
83
+ Beer.foreach( 'beer.csv' ) do |rec|
78
84
  puts "#{rec.name} (#{rec.abv}%) by #{rec.brewery}, #{rec.city}"
79
85
  end
80
86
  ```
81
87
 
88
+
82
89
  printing:
83
90
 
84
91
  ```
@@ -97,11 +104,11 @@ Or create new records from scratch. Example:
97
104
  beer = Beer.new( 'Andechser Klosterbrauerei',
98
105
  'Andechs',
99
106
  'Doppelbock Dunkel',
100
- '7.0%' )
107
+ '7%' )
101
108
 
102
109
  # -or-
103
110
 
104
- values = ['Andechser Klosterbrauerei', 'Andechs', 'Doppelbock Dunkel', '7.0%']
111
+ values = ['Andechser Klosterbrauerei', 'Andechs', 'Doppelbock Dunkel', '7%']
105
112
  beer = Beer.new( values )
106
113
 
107
114
  # -or-
@@ -109,14 +116,14 @@ beer = Beer.new( values )
109
116
  beer = Beer.new( brewery: 'Andechser Klosterbrauerei',
110
117
  city: 'Andechs',
111
118
  name: 'Doppelbock Dunkel',
112
- abv: '7.0%' )
119
+ abv: '7%' )
113
120
 
114
121
  # -or-
115
122
 
116
123
  hash = { brewery: 'Andechser Klosterbrauerei',
117
124
  city: 'Andechs',
118
125
  name: 'Doppelbock Dunkel',
119
- abv: '7.0%' }
126
+ abv: '7%' }
120
127
  beer = Beer.new( hash )
121
128
 
122
129
 
@@ -126,24 +133,24 @@ beer = Beer.new
126
133
  beer.update( brewery: 'Andechser Klosterbrauerei',
127
134
  city: 'Andechs',
128
135
  name: 'Doppelbock Dunkel' )
129
- beer.update( abv: 12.7 )
136
+ beer.update( abv: 7.0 )
130
137
 
131
138
  # -or-
132
139
 
133
140
  beer = Beer.new
134
- beer.parse( ['Andechser Klosterbrauerei', 'Andechs', 'Doppelbock Dunkel', '7.0%'] )
141
+ beer.parse( ['Andechser Klosterbrauerei', 'Andechs', 'Doppelbock Dunkel', '7%'] )
135
142
 
136
143
  # -or-
137
144
 
138
145
  beer = Beer.new
139
- beer.parse( 'Andechser Klosterbrauerei,Andechs,Doppelbock Dunkel,7.0%' )
146
+ beer.parse( 'Andechser Klosterbrauerei,Andechs,Doppelbock Dunkel,7%' )
140
147
 
141
148
  # -or-
142
149
 
143
150
  beer = Beer.new
144
151
  beer.brewery = 'Andechser Klosterbrauerei'
145
152
  beer.name = 'Doppelbock Dunkel'
146
- beer.abv = 12.7
153
+ beer.abv = 7.0
147
154
  ```
148
155
 
149
156
 
data/lib/csvrecord.rb CHANGED
@@ -10,6 +10,7 @@ require 'pp'
10
10
  require 'csvrecord/version' # let version always go first
11
11
  require 'csvrecord/base'
12
12
  require 'csvrecord/builder'
13
+ require 'csvrecord/reader'
13
14
 
14
15
 
15
16
 
@@ -100,6 +100,40 @@ module CsvRecord
100
100
  end
101
101
 
102
102
 
103
+ ###########################################
104
+ ## "magic" lazy auto-build schema from headers versions
105
+
106
+ def self.build_class( headers ) ## check: find a better name - why? why not?
107
+ ## (auto-)build record class from an array of headers
108
+ ## add fields (all types will be string for now)
109
+ clazz = Class.new(Base)
110
+ headers.each do |header|
111
+ ## downcase and remove all non-ascii chars etc.
112
+ ## todo/fix: remove all non-ascii chars!!!
113
+ ## todo: check if header starts with a number too!!
114
+ name = header.downcase.gsub( ' ', '_' )
115
+ name = name.to_sym ## symbol-ify
116
+ clazz.field( name )
117
+ end
118
+ clazz
119
+ end
120
+
121
+ def self.read( path, sep: Csv.config.sep )
122
+ headers = CsvReader.header( path, sep: sep )
123
+
124
+ clazz = build_class( headers )
125
+ clazz.read( path, sep: sep )
126
+ end
127
+
128
+ def self.foreach( path, sep: Csv.config.sep, &block )
129
+ headers = CsvReader.header( path, sep: sep )
130
+
131
+ clazz = build_class( headers )
132
+ clazz.foreach( path, sep: sep, &block )
133
+ end
134
+
135
+
136
+
103
137
 
104
138
  class Base
105
139
 
@@ -234,11 +268,21 @@ def to_csv ## use/rename/alias to to_row too - why? why not?
234
268
  end
235
269
 
236
270
 
271
+ def self.foreach( path, sep: Csv.config.sep, headers: true )
272
+ CsvReader.foreach( path, sep: sep, headers: headers ) do |row|
273
+ rec = new
274
+ values = CsvReader.unwrap( row )
275
+ rec.parse( values )
276
+
277
+ yield( rec ) ## check: use block.class( rec ) - why? why not?
278
+ end
279
+ end
280
+
237
281
 
238
- def self.parse( txt_or_rows ) ## note: returns an (lazy) enumarator
282
+ def self.parse( txt_or_rows, sep: Csv.config.sep, headers: true ) ## note: returns an (lazy) enumarator
239
283
  if txt_or_rows.is_a? String
240
284
  txt = txt_or_rows
241
- rows = CSV.parse( txt, headers: true )
285
+ rows = CsvReader.parse( txt, sep: sep, headers: headers )
242
286
  else
243
287
  ### todo/fix: use only self.create( array-like ) for array-like data - why? why not?
244
288
  rows = txt_or_rows ## assume array-like records that responds to :each
@@ -248,25 +292,19 @@ def self.parse( txt_or_rows ) ## note: returns an (lazy) enumarator
248
292
 
249
293
  Enumerator.new do |yielder|
250
294
  rows.each do |row|
251
- ## check - check for to_h - why? why not? supported/built-into by CSV::Row??
252
- ## if row.respond_to?( :to_h )
253
- ## else
254
- ## pp row.fields
255
- ## pp row.to_hash
256
- ## fix/todo!!!!!!!!!!!!!
257
- ## check for CSV::Row etc. - use row.to_hash ?
258
- rec = new
259
- rec.parse( row.fields )
260
- ## end
261
- yielder.yield( rec )
295
+ rec = new
296
+ values = CsvReader.unwrap( row )
297
+ rec.parse( values )
298
+
299
+ yielder.yield( rec )
262
300
  end
263
301
  end
264
302
  end
265
303
 
266
304
 
267
- def self.read( path ) ## not returns an enumarator
305
+ def self.read( path, sep: Csv.config.sep, headers: true ) ## not returns an enumarator
268
306
  txt = File.open( path, 'r:utf-8' ).read
269
- parse( txt )
307
+ parse( txt, sep: sep, headers: headers )
270
308
  end
271
309
 
272
310
 
@@ -0,0 +1,188 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ module Csv ## check: rename to CsvSettings / CsvPref / CsvGlobals or similar - why? why not???
5
+
6
+ ## STD_CSV_ENGINE = CSV ## to avoid name confusion use longer name - why? why not? find a better name?
7
+ ## use __CSV__ or similar? or just ::CSV ??
8
+
9
+ class Configuration
10
+
11
+ puts "CSV::VERSION:"
12
+ puts CSV::VERSION
13
+
14
+ puts "builtin CSV::Converters:"
15
+ pp CSV::Converters
16
+
17
+ puts "CSV::DEFAULT_OPTIONS:"
18
+ pp CSV::DEFAULT_OPTIONS
19
+
20
+ ## register our own converters
21
+ ## check if strip gets called for nil values too?
22
+ CSV::Converters[:strip] = ->(field) { field.strip }
23
+
24
+
25
+ attr_accessor :sep ## col_sep (column separator)
26
+
27
+ def initialize
28
+ @sep = ','
29
+ ## note: do NOT add headers as global - should ALWAYS be explicit
30
+ ## headers (true/false) - changes resultset and requires different processing!!!
31
+
32
+ self ## return self for chaining
33
+ end
34
+
35
+ def blank?( line )
36
+ ## note: blank line does NOT include "blank" with spaces only!!
37
+ ## use BLANK_REGEX in skip_lines to clean-up/skip/remove/ignore
38
+ ## see skip_blanks in default_options
39
+ line.empty?
40
+ end
41
+
42
+ ## lines starting with # (note: only leading spaces allowed)
43
+ COMMENTS_REGEX = /^\s*#/
44
+ BLANK_REGEX = /^\s*$/ ## skip all whitespace lines - note: use "" or , for a blank record!!!
45
+ SKIP_REGEX = Regexp.union( COMMENTS_REGEX, BLANK_REGEX )
46
+
47
+ def skip?( line )
48
+ ## check if comment line - skip comments
49
+ ## see skip_lines in default_options
50
+ line =~ SKIP_REGEX
51
+ end
52
+
53
+ ## built-in (default) options
54
+ ## todo: find a better name?
55
+ def default_options
56
+ ## note:
57
+ ## do NOT include sep character and
58
+ ## do NOT include headers true/false here
59
+ ##
60
+ ## make default sep its own "global" default config
61
+ ## e.g. Csv.config.sep =
62
+
63
+ ## common options
64
+ ## skip comments starting with #
65
+ ## skip blank lines
66
+ ## strip leading and trailing spaces
67
+ ## NOTE/WARN: leading and trailing spaces NOT allowed/working with double quoted values!!!!
68
+ defaults = {
69
+ skip_blanks: true, ## note: skips lines with no whitespaces only!! (e.g. line with space is NOT blank!!)
70
+ skip_lines: SKIP_REGEX,
71
+ :converters => :strip
72
+ }
73
+ defaults
74
+ end
75
+ end # class Configuration
76
+
77
+
78
+ ## lets you use
79
+ ## Csv.configure do |config|
80
+ ## config.sep = ',' ## or "/t"
81
+ ## end
82
+
83
+ def self.configure
84
+ yield( config )
85
+ end
86
+
87
+ def self.config
88
+ @config ||= Configuration.new
89
+ end
90
+ end # module Csvv
91
+
92
+
93
+
94
+ ####
95
+ ## use our own wrapper
96
+
97
+ class CsvReader
98
+
99
+ ####################
100
+ # helper methods
101
+ def self.unwrap( row_or_array ) ## unwrap row - find a better name? why? why not?
102
+ ## return row values as array of strings
103
+ if row_or_array.is_a?( CSV::Row )
104
+ row = row_or_array
105
+ row.fields ## gets array of string of field values
106
+ else ## assume "classic" array of strings
107
+ array = row_or_array
108
+ end
109
+ end
110
+
111
+
112
+
113
+ def self.foreach( path, sep: Csv.config.sep, headers: true )
114
+ csv_options = Csv.config.default_options.merge(
115
+ headers: headers,
116
+ col_sep: sep,
117
+ external_encoding: 'utf-8' ## note: always (auto-)add utf-8 external encoding for now!!!
118
+ )
119
+
120
+ CSV.foreach( path, csv_options ) do |row|
121
+ yield( row ) ## check/todo: use block.call( row ) ## why? why not?
122
+ end
123
+ end
124
+
125
+
126
+ def self.read( path, sep: Csv.config.sep, headers: true )
127
+ ## note: use our own file.open
128
+ ## always use utf-8 for now
129
+ ## check/todo: add skip option bom too - why? why not?
130
+ txt = File.open( path, 'r:utf-8' )
131
+ parse( txt, sep: sep, headers: headers )
132
+ end
133
+
134
+ def self.parse( txt, sep: Csv.config.sep, headers: true )
135
+ csv_options = Csv.config.default_options.merge(
136
+ headers: headers,
137
+ col_sep: sep
138
+ )
139
+ ## pp csv_options
140
+ CSV.parse( txt, csv_options )
141
+ end
142
+
143
+ def self.parse_line( txt, sep: Csv.config.sep )
144
+ ## note: do NOT include headers option (otherwise single row gets skipped as first header row :-)
145
+ csv_options = Csv.config.default_options.merge(
146
+ headers: false, ## note: always turn off headers!!!!!!
147
+ col_sep: sep
148
+ )
149
+ ## pp csv_options
150
+ CSV.parse_line( txt, csv_options )
151
+ end
152
+
153
+
154
+
155
+ def self.header( path, sep: Csv.config.sep ) ## use header or headers - or use both (with alias)?
156
+ # read first lines (only)
157
+ # and parse with csv to get header from csv library itself
158
+ #
159
+ # check - if there's an easier or built-in way for the csv library
160
+
161
+ ## readlines until
162
+ ## - NOT a comments line or
163
+ ## - NOT a blank line
164
+
165
+ lines = ''
166
+ File.open( path, 'r:utf-8' ) do |f|
167
+
168
+ ## todo/fix: how to handle empty files or files without headers?!
169
+
170
+ ## todo/check if readline includes \n\r too??
171
+ ## yes! - line include \n e.g.
172
+ ## "Brewery,City,Name,Abv\n" or
173
+ ## "#######\n# try with some comments\n# and blank lines even before header\n\nBrewery,City,Name,Abv\n"
174
+ loop do
175
+ line = f.readline
176
+ lines << line
177
+ break unless Csv.config.skip?( line ) || Csv.config.blank?( line )
178
+ end
179
+ end
180
+
181
+ ## puts "lines:"
182
+ ## pp lines
183
+
184
+ ## note: do NOT use headers: true to get "plain" data array (no hash records)
185
+ ## hash record does NOT work for single line/row
186
+ parse_line( lines, sep: sep )
187
+ end # method self.header
188
+ end # class CsvReader
@@ -4,7 +4,7 @@
4
4
  module CsvRecord
5
5
 
6
6
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
7
- MINOR = 2
7
+ MINOR = 3
8
8
  PATCH = 0
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
@@ -0,0 +1,51 @@
1
+ #######
2
+ # try with some comments
3
+ # and blank lines even before header
4
+
5
+ Brewery,City,Name,Abv
6
+ Andechser Klosterbrauerei,Andechs,Doppelbock Dunkel,7%
7
+ Augustiner Bräu München,München,Edelstoff,5.6%
8
+ Bayerische Staatsbrauerei Weihenstephan,Freising,Hefe Weissbier,5.4%
9
+
10
+ Brauerei Spezial, Bamberg, Rauchbier Märzen, 5.1%
11
+
12
+ Hacker-Pschorr Bräu, München, Münchner Dunkel, 5.0%
13
+
14
+ ## some more comments here
15
+
16
+ Staatliches Hofbräuhaus München,München,Hofbräu Oktoberfestbier,6.3%
17
+
18
+ ## check for nil
19
+ "", ,,"",
20
+
21
+ ## check for blank line with spaces
22
+ ## yes, will get added as a record!! e.g. ["", nil, nil, nil]
23
+ ## use regex to skip blank lines with spaces!!!!
24
+
25
+
26
+ ## test double quotes and double quotes escaped
27
+ ## note: double quotes do NOT work with leading AND/OR trailing spaces
28
+ ## leads to:
29
+ ## CSV::MalformedCSVError - Missing or stray quote in line xxx
30
+ ##
31
+ ## note: for now double quote does not accept leading AND/OR trailing spaces!!!!
32
+ ##
33
+ ## todo/fix: check liberal_quote option starting in csv ruby 2.4 ???
34
+ ##
35
+ ## examples:
36
+ ## "value with comma, comma","some ""hello""","some ""hello""",
37
+ ## works - but does NOT work (note the leading and trailing spaces for double quotes):
38
+ ## "value with comma, comma" ,"some ""hello""", "some ""hello""",
39
+ ##
40
+ ## check for "multi-line":
41
+ ## "hello
42
+ ## and another line
43
+ ## and another",two,three,
44
+
45
+
46
+ "value with comma, comma","some ""hello""","some ""hello""",
47
+
48
+ ## check for "multi-line"
49
+ "hello
50
+ and another line
51
+ and another",two,three,
@@ -0,0 +1,119 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_reader.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestReader < MiniTest::Test
11
+
12
+ def test_read
13
+ puts "== read: beer.csv:"
14
+ table = CsvReader.read( "#{CsvRecord.test_data_dir}/beer.csv" ) ## returns CSV::Table
15
+
16
+ pp table.class.name
17
+ pp table
18
+ pp table.to_a ## note: includes header (first row with column names)
19
+
20
+ table.each do |row| ## note: will skip (NOT include) header row!!
21
+ pp row
22
+ end
23
+ puts " #{table.size} rows" ## note: again will skip (NOT include) header row in count!!!
24
+ assert_equal 6, table.size
25
+ end
26
+
27
+ def test_read_header_false
28
+ puts "== read (headers: false): beer.csv:"
29
+ data = CsvReader.read( "#{CsvRecord.test_data_dir}/beer.csv", headers: false )
30
+
31
+ pp data.class.name
32
+ pp data
33
+
34
+ data.each do |row|
35
+ pp row
36
+ end
37
+ puts " #{data.size} rows"
38
+ assert_equal 7, data.size ## note: include header row in count
39
+ end
40
+
41
+
42
+ def test_read11
43
+ puts "== read: beer11.csv:"
44
+ table = CsvReader.read( "#{CsvRecord.test_data_dir}/beer11.csv" )
45
+ pp table
46
+ pp table.to_a ## note: includes header (first row with column names)
47
+
48
+ assert true
49
+ end
50
+
51
+
52
+ def test_parse_line
53
+ puts "== parse_line:"
54
+ row = CsvReader.parse_line( <<TXT )
55
+ Augustiner Bräu München, München, Edelstoff, 5.6%
56
+ Bayerische Staatsbrauerei Weihenstephan, Freising, Hefe Weissbier, 5.4%
57
+ TXT
58
+
59
+ pp row
60
+ assert_equal ['Augustiner Bräu München', 'München', 'Edelstoff', '5.6%'], row
61
+ end
62
+
63
+ def test_parse_line11
64
+ puts "== parse_line:"
65
+ row = CsvReader.parse_line( <<TXT )
66
+ #######
67
+ # try with some comments
68
+ # and blank lines even before header
69
+
70
+ Augustiner Bräu München, München, Edelstoff, 5.6%
71
+ Bayerische Staatsbrauerei Weihenstephan, Freising, Hefe Weissbier, 5.4%
72
+ TXT
73
+
74
+ pp row
75
+ assert_equal ['Augustiner Bräu München', 'München', 'Edelstoff', '5.6%'], row
76
+ end
77
+
78
+ def test_header
79
+ puts "== header: beer.csv:"
80
+ header = CsvReader.header( "#{CsvRecord.test_data_dir}/beer.csv" )
81
+ pp header
82
+ assert_equal ['Brewery','City','Name','Abv'], header
83
+ end
84
+
85
+ def test_header11
86
+ puts "== header: beer11.csv:"
87
+ header = CsvReader.header( "#{CsvRecord.test_data_dir}/beer11.csv" )
88
+ pp header
89
+ assert_equal ['Brewery','City','Name','Abv'], header
90
+ end
91
+
92
+
93
+ def test_foreach
94
+ puts "== foreach: beer.csv:"
95
+ CsvReader.foreach( "#{CsvRecord.test_data_dir}/beer.csv" ) do |row|
96
+ pp row
97
+ pp row.fields
98
+ end
99
+ assert true
100
+ end
101
+
102
+ def test_foreach11
103
+ puts "== foreach: beer11.csv:"
104
+ CsvReader.foreach( "#{CsvRecord.test_data_dir}/beer11.csv" ) do |row|
105
+ pp row
106
+ pp row.fields
107
+ end
108
+ assert true
109
+ end
110
+
111
+ def test_foreach_header_false
112
+ puts "== foreach (headers: false): beer11.csv:"
113
+ CsvReader.foreach( "#{CsvRecord.test_data_dir}/beer11.csv", headers: false ) do |row|
114
+ pp row ## note: is Array (no .fields available!!!!!)
115
+ end
116
+ assert true
117
+ end
118
+
119
+ end # class TestReader
@@ -2,21 +2,12 @@
2
2
 
3
3
  ###
4
4
  # to run use
5
- # ruby -I ./lib -I ./test test/test_beer.rb
5
+ # ruby -I ./lib -I ./test test/test_record.rb
6
6
 
7
7
 
8
8
  require 'helper'
9
9
 
10
- class TestBeer < MiniTest::Test
11
-
12
- def test_version
13
- pp CsvRecord::VERSION
14
- pp CsvRecord.banner
15
- pp CsvRecord.root
16
-
17
- assert true ## assume ok if we get here
18
- end
19
-
10
+ class TestRecord < MiniTest::Test
20
11
 
21
12
  def test_class_style1
22
13
  clazz1 = CsvRecord.define do
@@ -104,6 +95,35 @@ class TestBeer < MiniTest::Test
104
95
  assert true ## assume ok if we get here
105
96
  end
106
97
 
98
+
99
+ def test_foreach
100
+ puts "== foreach:"
101
+ Beer.foreach( "#{CsvRecord.test_data_dir}/beer.csv" ) do |rec|
102
+ puts "#{rec.name} (#{rec.abv}%) by #{rec.brewery}, #{rec.city}"
103
+ end
104
+
105
+ assert true ## assume ok if we get here
106
+ end
107
+
108
+
109
+ def test_parse_array_or_arrays
110
+ data=[
111
+ ['Brewery','City','Name','Abv'],
112
+ ['Andechser Klosterbrauerei','Andechs','Doppelbock Dunkel','7%'],
113
+ ['Augustiner Bräu München','München','Edelstoff','5.6%'],
114
+ ['Bayerische Staatsbrauerei Weihenstephan','Freising','Hefe Weissbier','5.4%'],
115
+ ['Brauerei Spezial','Bamberg','Rauchbier Märzen','5.1%'],
116
+ ['Hacker-Pschorr Bräu','München','Münchner Dunkel','5.0%'],
117
+ ['Staatliches Hofbräuhaus München','München','Hofbräu Oktoberfestbier','6.3%']]
118
+
119
+ beers = Beer.parse( data ).to_a
120
+ puts "#{beers.size} beers:"
121
+ pp beers
122
+
123
+ assert true ## assume ok if we get here
124
+ end
125
+
126
+
107
127
  def test_classic
108
128
  puts "== read( data ).to_a:"
109
129
  beers = BeerClassic.read( "#{CsvRecord.test_data_dir}/beer.csv" ).to_a
@@ -227,4 +247,4 @@ class TestBeer < MiniTest::Test
227
247
  assert_equal values[3].to_f, beer['Abv']
228
248
  end
229
249
 
230
- end # class TestBeer
250
+ end # class TestRecord
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_record_auto.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestRecordAuto < MiniTest::Test
11
+
12
+
13
+ def test_read
14
+ beers = CsvRecord.read( "#{CsvRecord.test_data_dir}/beer.csv" ).to_a
15
+ pp beers
16
+
17
+ assert_equal 6, beers.size
18
+ assert_equal 'Andechser Klosterbrauerei', beers[0].brewery
19
+ assert_equal 'Andechs', beers[0].city
20
+ assert_equal 'Doppelbock Dunkel', beers[0].name
21
+ assert_equal '7%', beers[0].abv
22
+ end
23
+
24
+
25
+ def test_foreach
26
+ CsvRecord.foreach( "#{CsvRecord.test_data_dir}/beer.csv" ) do |rec|
27
+ pp rec
28
+ puts "#{rec.name} (#{rec.abv}%) by #{rec.brewery}, #{rec.city}"
29
+ end
30
+
31
+ assert true
32
+ end
33
+
34
+ end # class TestRecordAuto
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_version.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestVersion < MiniTest::Test
11
+
12
+ def test_version
13
+ pp CsvRecord::VERSION
14
+ pp CsvRecord.banner
15
+ pp CsvRecord.root
16
+
17
+ assert true ## assume ok if we get here
18
+ end
19
+
20
+ end # class TestVersion
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csvrecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-13 00:00:00.000000000 Z
11
+ date: 2018-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -57,10 +57,15 @@ files:
57
57
  - lib/csvrecord.rb
58
58
  - lib/csvrecord/base.rb
59
59
  - lib/csvrecord/builder.rb
60
+ - lib/csvrecord/reader.rb
60
61
  - lib/csvrecord/version.rb
61
62
  - test/data/beer.csv
63
+ - test/data/beer11.csv
62
64
  - test/helper.rb
63
- - test/test_beer.rb
65
+ - test/test_reader.rb
66
+ - test/test_record.rb
67
+ - test/test_record_auto.rb
68
+ - test/test_version.rb
64
69
  homepage: https://github.com/csv11/csvrecord
65
70
  licenses:
66
71
  - Public Domain