csv 3.1.6 → 3.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +20 -0
- data/doc/{arguments → csv/arguments}/io.rdoc +0 -0
- data/doc/{options → csv/options}/common/col_sep.rdoc +0 -0
- data/doc/{options → csv/options}/common/quote_char.rdoc +0 -0
- data/doc/{options → csv/options}/common/row_sep.rdoc +0 -0
- data/doc/{options → csv/options}/generating/force_quotes.rdoc +0 -0
- data/doc/{options → csv/options}/generating/quote_empty.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_converters.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_empty_value.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_headers.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_nil_value.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/converters.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/empty_value.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/field_size_limit.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/header_converters.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/headers.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/liberal_parsing.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/nil_value.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/return_headers.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/skip_blanks.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/skip_lines.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/strip.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/unconverted_fields.rdoc +0 -0
- data/lib/csv.rb +142 -46
- data/lib/csv/table.rb +285 -64
- data/lib/csv/version.rb +1 -1
- metadata +26 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c834580f6d364830ddcd85b07edcb44fc91520fd594492a835cb57f43f145c94
|
4
|
+
data.tar.gz: 989310760b22148eeb70be9181a39c2d08c8040f7e79fd6a06dc7586409c4e7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75859dd4eff126ab15bf372305da6eeb638ce1927186931f3ea87fe00c0a769c8adb38cb786b8ee3f7fd418de720d26fe01fba9ca28ac565bbd761431057cec8
|
7
|
+
data.tar.gz: 56b5de70961f3e9792296e6b68941fa1ea1e1eaa5ad2811ae47954a775c986d8f9455af50e5e6d25deb797794b697cef0e0c4a87695dc3a42d9fa477008d85dc
|
data/NEWS.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 3.1.7 - 2020-08-04
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Improved document.
|
8
|
+
[GitHub#158][GitHub#160][GitHub#161]
|
9
|
+
[Patch by Burdette Lamar]
|
10
|
+
|
11
|
+
* Updated required Ruby version to 2.5.0 or later.
|
12
|
+
[GitHub#159]
|
13
|
+
[Patch by Gabriel Nagy]
|
14
|
+
|
15
|
+
* Removed stringio 0.1.3 or later dependency.
|
16
|
+
|
17
|
+
### Thanks
|
18
|
+
|
19
|
+
* Burdette Lamar
|
20
|
+
|
21
|
+
* Gabriel Nagy
|
22
|
+
|
3
23
|
## 3.1.6 - 2020-07-20
|
4
24
|
|
5
25
|
### Improvements
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/csv.rb
CHANGED
@@ -104,7 +104,7 @@ require_relative "csv/writer"
|
|
104
104
|
using CSV::MatchP if CSV.const_defined?(:MatchP)
|
105
105
|
|
106
106
|
# == \CSV
|
107
|
-
# \CSV (comma-separated
|
107
|
+
# \CSV (comma-separated values) data is a text representation of a table:
|
108
108
|
# - A _row_ _separator_ delimits table rows.
|
109
109
|
# A common row separator is the newline character <tt>"\n"</tt>.
|
110
110
|
# - A _column_ _separator_ delimits fields in a row.
|
@@ -357,35 +357,35 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
357
357
|
# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field.
|
358
358
|
# - +empty_value+: Specifies the object that is to be substituted for each empty field.
|
359
359
|
#
|
360
|
-
# :include: ../doc/options/common/row_sep.rdoc
|
360
|
+
# :include: ../doc/csv/options/common/row_sep.rdoc
|
361
361
|
#
|
362
|
-
# :include: ../doc/options/common/col_sep.rdoc
|
362
|
+
# :include: ../doc/csv/options/common/col_sep.rdoc
|
363
363
|
#
|
364
|
-
# :include: ../doc/options/common/quote_char.rdoc
|
364
|
+
# :include: ../doc/csv/options/common/quote_char.rdoc
|
365
365
|
#
|
366
|
-
# :include: ../doc/options/parsing/field_size_limit.rdoc
|
366
|
+
# :include: ../doc/csv/options/parsing/field_size_limit.rdoc
|
367
367
|
#
|
368
|
-
# :include: ../doc/options/parsing/converters.rdoc
|
368
|
+
# :include: ../doc/csv/options/parsing/converters.rdoc
|
369
369
|
#
|
370
|
-
# :include: ../doc/options/parsing/unconverted_fields.rdoc
|
370
|
+
# :include: ../doc/csv/options/parsing/unconverted_fields.rdoc
|
371
371
|
#
|
372
|
-
# :include: ../doc/options/parsing/headers.rdoc
|
372
|
+
# :include: ../doc/csv/options/parsing/headers.rdoc
|
373
373
|
#
|
374
|
-
# :include: ../doc/options/parsing/return_headers.rdoc
|
374
|
+
# :include: ../doc/csv/options/parsing/return_headers.rdoc
|
375
375
|
#
|
376
|
-
# :include: ../doc/options/parsing/header_converters.rdoc
|
376
|
+
# :include: ../doc/csv/options/parsing/header_converters.rdoc
|
377
377
|
#
|
378
|
-
# :include: ../doc/options/parsing/skip_blanks.rdoc
|
378
|
+
# :include: ../doc/csv/options/parsing/skip_blanks.rdoc
|
379
379
|
#
|
380
|
-
# :include: ../doc/options/parsing/skip_lines.rdoc
|
380
|
+
# :include: ../doc/csv/options/parsing/skip_lines.rdoc
|
381
381
|
#
|
382
|
-
# :include: ../doc/options/parsing/strip.rdoc
|
382
|
+
# :include: ../doc/csv/options/parsing/strip.rdoc
|
383
383
|
#
|
384
|
-
# :include: ../doc/options/parsing/liberal_parsing.rdoc
|
384
|
+
# :include: ../doc/csv/options/parsing/liberal_parsing.rdoc
|
385
385
|
#
|
386
|
-
# :include: ../doc/options/parsing/nil_value.rdoc
|
386
|
+
# :include: ../doc/csv/options/parsing/nil_value.rdoc
|
387
387
|
#
|
388
|
-
# :include: ../doc/options/parsing/empty_value.rdoc
|
388
|
+
# :include: ../doc/csv/options/parsing/empty_value.rdoc
|
389
389
|
#
|
390
390
|
# ==== Options for Generating
|
391
391
|
#
|
@@ -400,23 +400,23 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
400
400
|
# - +write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field.
|
401
401
|
# - +write_empty_value+: Specifies the object that is to be substituted for each empty field.
|
402
402
|
#
|
403
|
-
# :include: ../doc/options/common/row_sep.rdoc
|
403
|
+
# :include: ../doc/csv/options/common/row_sep.rdoc
|
404
404
|
#
|
405
|
-
# :include: ../doc/options/common/col_sep.rdoc
|
405
|
+
# :include: ../doc/csv/options/common/col_sep.rdoc
|
406
406
|
#
|
407
|
-
# :include: ../doc/options/common/quote_char.rdoc
|
407
|
+
# :include: ../doc/csv/options/common/quote_char.rdoc
|
408
408
|
#
|
409
|
-
# :include: ../doc/options/generating/write_headers.rdoc
|
409
|
+
# :include: ../doc/csv/options/generating/write_headers.rdoc
|
410
410
|
#
|
411
|
-
# :include: ../doc/options/generating/force_quotes.rdoc
|
411
|
+
# :include: ../doc/csv/options/generating/force_quotes.rdoc
|
412
412
|
#
|
413
|
-
# :include: ../doc/options/generating/quote_empty.rdoc
|
413
|
+
# :include: ../doc/csv/options/generating/quote_empty.rdoc
|
414
414
|
#
|
415
|
-
# :include: ../doc/options/generating/write_converters.rdoc
|
415
|
+
# :include: ../doc/csv/options/generating/write_converters.rdoc
|
416
416
|
#
|
417
|
-
# :include: ../doc/options/generating/write_nil_value.rdoc
|
417
|
+
# :include: ../doc/csv/options/generating/write_nil_value.rdoc
|
418
418
|
#
|
419
|
-
# :include: ../doc/options/generating/write_empty_value.rdoc
|
419
|
+
# :include: ../doc/csv/options/generating/write_empty_value.rdoc
|
420
420
|
#
|
421
421
|
# === \CSV with Headers
|
422
422
|
#
|
@@ -1075,7 +1075,7 @@ class CSV
|
|
1075
1075
|
# Calls the block with each row read from source +path+ or +io+.
|
1076
1076
|
#
|
1077
1077
|
# * Argument +path+, if given, must be the path to a file.
|
1078
|
-
# :include: ../doc/arguments/io.rdoc
|
1078
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1079
1079
|
# * Argument +mode+, if given, must be a \File mode
|
1080
1080
|
# See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
|
1081
1081
|
# * Arguments <tt>**options</tt> must be keyword options.
|
@@ -1322,7 +1322,7 @@ class CSV
|
|
1322
1322
|
# :replace => string # replacement string ("?" or "\uFFFD" if not specified)
|
1323
1323
|
#
|
1324
1324
|
# * Argument +path+, if given, must be the path to a file.
|
1325
|
-
# :include: ../doc/arguments/io.rdoc
|
1325
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1326
1326
|
# * Argument +mode+, if given, must be a \File mode
|
1327
1327
|
# See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
|
1328
1328
|
# * Arguments <tt>**options</tt> must be keyword options.
|
@@ -1427,7 +1427,7 @@ class CSV
|
|
1427
1427
|
#
|
1428
1428
|
# - Argument +string+ should be a \String object;
|
1429
1429
|
# it will be put into a new StringIO object positioned at the beginning.
|
1430
|
-
# :include: ../doc/arguments/io.rdoc
|
1430
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1431
1431
|
# - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1432
1432
|
#
|
1433
1433
|
# ====== Without Option +headers+
|
@@ -1552,7 +1552,7 @@ class CSV
|
|
1552
1552
|
#
|
1553
1553
|
# - Argument +string+ should be a \String object;
|
1554
1554
|
# it will be put into a new StringIO object positioned at the beginning.
|
1555
|
-
# :include: ../doc/arguments/io.rdoc
|
1555
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1556
1556
|
# - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1557
1557
|
#
|
1558
1558
|
# ====== Without Option +headers+
|
@@ -1672,7 +1672,7 @@ class CSV
|
|
1672
1672
|
#
|
1673
1673
|
# - Argument +string+ should be a \String object;
|
1674
1674
|
# it will be put into a new StringIO object positioned at the beginning.
|
1675
|
-
# :include: ../doc/arguments/io.rdoc
|
1675
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1676
1676
|
# - Argument +options+: See:
|
1677
1677
|
# * {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1678
1678
|
# * {Options for Generating}[#class-CSV-label-Options+for+Generating]
|
@@ -2080,7 +2080,7 @@ class CSV
|
|
2080
2080
|
### End Delegation ###
|
2081
2081
|
|
2082
2082
|
# :call-seq:
|
2083
|
-
# csv
|
2083
|
+
# csv << row -> self
|
2084
2084
|
#
|
2085
2085
|
# Appends a row to +self+.
|
2086
2086
|
#
|
@@ -2120,7 +2120,7 @@ class CSV
|
|
2120
2120
|
# csv << :foo
|
2121
2121
|
# end
|
2122
2122
|
#
|
2123
|
-
# Raises an exception if the output stream is not
|
2123
|
+
# Raises an exception if the output stream is not opened for writing:
|
2124
2124
|
# path = 't.csv'
|
2125
2125
|
# File.write(path, '')
|
2126
2126
|
# File.open(path) do |file|
|
@@ -2272,25 +2272,57 @@ class CSV
|
|
2272
2272
|
|
2273
2273
|
include Enumerable
|
2274
2274
|
|
2275
|
+
# :call-seq:
|
2276
|
+
# csv.each -> enumerator
|
2277
|
+
# csv.each {|row| ...}
|
2275
2278
|
#
|
2276
|
-
#
|
2279
|
+
# Calls the block with each successive row.
|
2280
|
+
# The data source must be opened for reading.
|
2277
2281
|
#
|
2278
|
-
#
|
2282
|
+
# Without headers:
|
2283
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2284
|
+
# csv = CSV.new(string)
|
2285
|
+
# csv.each do |row|
|
2286
|
+
# p row
|
2287
|
+
# end
|
2288
|
+
# Output:
|
2289
|
+
# ["foo", "0"]
|
2290
|
+
# ["bar", "1"]
|
2291
|
+
# ["baz", "2"]
|
2279
2292
|
#
|
2280
|
-
#
|
2293
|
+
# With headers:
|
2294
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2295
|
+
# csv = CSV.new(string, headers: true)
|
2296
|
+
# csv.each do |row|
|
2297
|
+
# p row
|
2298
|
+
# end
|
2299
|
+
# Output:
|
2300
|
+
# <CSV::Row "Name":"foo" "Value":"0">
|
2301
|
+
# <CSV::Row "Name":"bar" "Value":"1">
|
2302
|
+
# <CSV::Row "Name":"baz" "Value":"2">
|
2303
|
+
#
|
2304
|
+
# ---
|
2281
2305
|
#
|
2306
|
+
# Raises an exception if the source is not opened for reading:
|
2307
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2308
|
+
# csv = CSV.new(string)
|
2309
|
+
# csv.close
|
2310
|
+
# # Raises IOError (not opened for reading)
|
2311
|
+
# csv.each do |row|
|
2312
|
+
# p row
|
2313
|
+
# end
|
2282
2314
|
def each(&block)
|
2283
2315
|
parser_enumerator.each(&block)
|
2284
2316
|
end
|
2285
2317
|
|
2286
2318
|
# :call-seq:
|
2287
|
-
#
|
2319
|
+
# csv.read -> array or csv_table
|
2288
2320
|
#
|
2289
2321
|
# Forms the remaining rows from +self+ into:
|
2290
2322
|
# - A CSV::Table object, if headers are in use.
|
2291
|
-
# - An Array of Arrays, otherwise.
|
2323
|
+
# - An \Array of Arrays, otherwise.
|
2292
2324
|
#
|
2293
|
-
# The data source must be
|
2325
|
+
# The data source must be opened for reading.
|
2294
2326
|
#
|
2295
2327
|
# Without headers:
|
2296
2328
|
# string = "foo,0\nbar,1\nbaz,2\n"
|
@@ -2305,6 +2337,15 @@ class CSV
|
|
2305
2337
|
# File.write(path, string)
|
2306
2338
|
# csv = CSV.open(path, headers: true)
|
2307
2339
|
# csv.read # => #<CSV::Table mode:col_or_row row_count:4>
|
2340
|
+
#
|
2341
|
+
# ---
|
2342
|
+
#
|
2343
|
+
# Raises an exception if the source is not opened for reading:
|
2344
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2345
|
+
# csv = CSV.new(string)
|
2346
|
+
# csv.close
|
2347
|
+
# # Raises IOError (not opened for reading)
|
2348
|
+
# csv.read
|
2308
2349
|
def read
|
2309
2350
|
rows = to_a
|
2310
2351
|
if parser.use_headers?
|
@@ -2315,18 +2356,69 @@ class CSV
|
|
2315
2356
|
end
|
2316
2357
|
alias_method :readlines, :read
|
2317
2358
|
|
2318
|
-
#
|
2359
|
+
# :call-seq:
|
2360
|
+
# csv.header_row? -> true or false
|
2361
|
+
#
|
2362
|
+
# Returns +true+ if the next row to be read is a header row\;
|
2363
|
+
# +false+ otherwise.
|
2364
|
+
#
|
2365
|
+
# Without headers:
|
2366
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2367
|
+
# csv = CSV.new(string)
|
2368
|
+
# csv.header_row? # => false
|
2369
|
+
#
|
2370
|
+
# With headers:
|
2371
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2372
|
+
# csv = CSV.new(string, headers: true)
|
2373
|
+
# csv.header_row? # => true
|
2374
|
+
# csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
|
2375
|
+
# csv.header_row? # => false
|
2376
|
+
#
|
2377
|
+
# ---
|
2378
|
+
#
|
2379
|
+
# Raises an exception if the source is not opened for reading:
|
2380
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2381
|
+
# csv = CSV.new(string)
|
2382
|
+
# csv.close
|
2383
|
+
# # Raises IOError (not opened for reading)
|
2384
|
+
# csv.header_row?
|
2319
2385
|
def header_row?
|
2320
2386
|
parser.header_row?
|
2321
2387
|
end
|
2322
2388
|
|
2389
|
+
# :call-seq:
|
2390
|
+
# csv.shift -> array, csv_row, or nil
|
2323
2391
|
#
|
2324
|
-
#
|
2325
|
-
#
|
2326
|
-
#
|
2392
|
+
# Returns the next row of data as:
|
2393
|
+
# - An \Array if no headers are used.
|
2394
|
+
# - A CSV::Row object if headers are used.
|
2327
2395
|
#
|
2328
|
-
# The data source must be
|
2396
|
+
# The data source must be opened for reading.
|
2329
2397
|
#
|
2398
|
+
# Without headers:
|
2399
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2400
|
+
# csv = CSV.new(string)
|
2401
|
+
# csv.shift # => ["foo", "0"]
|
2402
|
+
# csv.shift # => ["bar", "1"]
|
2403
|
+
# csv.shift # => ["baz", "2"]
|
2404
|
+
# csv.shift # => nil
|
2405
|
+
#
|
2406
|
+
# With headers:
|
2407
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2408
|
+
# csv = CSV.new(string, headers: true)
|
2409
|
+
# csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
|
2410
|
+
# csv.shift # => #<CSV::Row "Name":"bar" "Value":"1">
|
2411
|
+
# csv.shift # => #<CSV::Row "Name":"baz" "Value":"2">
|
2412
|
+
# csv.shift # => nil
|
2413
|
+
#
|
2414
|
+
# ---
|
2415
|
+
#
|
2416
|
+
# Raises an exception if the source is not opened for reading:
|
2417
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2418
|
+
# csv = CSV.new(string)
|
2419
|
+
# csv.close
|
2420
|
+
# # Raises IOError (not opened for reading)
|
2421
|
+
# csv.shift
|
2330
2422
|
def shift
|
2331
2423
|
if @eof_error
|
2332
2424
|
eof_error, @eof_error = @eof_error, nil
|
@@ -2341,10 +2433,14 @@ class CSV
|
|
2341
2433
|
alias_method :gets, :shift
|
2342
2434
|
alias_method :readline, :shift
|
2343
2435
|
|
2436
|
+
# :call-seq:
|
2437
|
+
# csv.inspect -> string
|
2344
2438
|
#
|
2345
|
-
# Returns a
|
2346
|
-
#
|
2347
|
-
#
|
2439
|
+
# Returns a \String showing certain properties of +self+:
|
2440
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2441
|
+
# csv = CSV.new(string, headers: true)
|
2442
|
+
# s = csv.inspect
|
2443
|
+
# s # => "#<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:\",\" row_sep:\"\\n\" quote_char:\"\\\"\" headers:true>"
|
2348
2444
|
def inspect
|
2349
2445
|
str = ["#<", self.class.to_s, " io_type:"]
|
2350
2446
|
# show type of wrapped IO
|
data/lib/csv/table.rb
CHANGED
@@ -3,31 +3,199 @@
|
|
3
3
|
require "forwardable"
|
4
4
|
|
5
5
|
class CSV
|
6
|
+
# = \CSV::Table
|
7
|
+
# A \CSV::Table instance is an object representing \CSV data.
|
8
|
+
# (see {class CSV}[../CSV.html]).
|
6
9
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
+
# The instance may have:
|
11
|
+
# - Rows: each is a Table::Row object.
|
12
|
+
# - Headers: names for the columns.
|
10
13
|
#
|
11
|
-
#
|
12
|
-
# row processing is activated.
|
14
|
+
# === Instance Methods
|
13
15
|
#
|
16
|
+
# \CSV::Table has three groups of instance methods:
|
17
|
+
# - Its own internally defined instance methods.
|
18
|
+
# - Methods included by module Enumerable.
|
19
|
+
# - Methods delegated to class Array.:
|
20
|
+
# * Array#empty?
|
21
|
+
# * Array#length
|
22
|
+
# * Array#size
|
23
|
+
#
|
24
|
+
# == Creating a \CSV::Table Instance
|
25
|
+
#
|
26
|
+
# Commonly, a new \CSV::Table instance is created by parsing \CSV source
|
27
|
+
# using headers:
|
28
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
29
|
+
# table = CSV.parse(source, headers: true)
|
30
|
+
# table.class # => CSV::Table
|
31
|
+
#
|
32
|
+
# You can also create an instance directly. See ::new.
|
33
|
+
#
|
34
|
+
# == Headers
|
35
|
+
#
|
36
|
+
# If a table has headers, the headers serve as labels for the columns of data.
|
37
|
+
# Each header serves as the label for its column.
|
38
|
+
#
|
39
|
+
# The headers for a \CSV::Table object are stored as an \Array of Strings.
|
40
|
+
#
|
41
|
+
# Commonly, headers are defined in the first row of \CSV source:
|
42
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
43
|
+
# table = CSV.parse(source, headers: true)
|
44
|
+
# table.headers # => ["Name", "Value"]
|
45
|
+
#
|
46
|
+
# If no headers are defined, the \Array is empty:
|
47
|
+
# table = CSV::Table.new([])
|
48
|
+
# table.headers # => []
|
49
|
+
#
|
50
|
+
# == Access Modes
|
51
|
+
#
|
52
|
+
# \CSV::Table provides three modes for accessing table data:
|
53
|
+
# - \Row mode.
|
54
|
+
# - Column mode.
|
55
|
+
# - Mixed mode (the default for a new table).
|
56
|
+
#
|
57
|
+
# The access mode for a\CSV::Table instance affects the behavior
|
58
|
+
# of some of its instance methods:
|
59
|
+
# - #[]
|
60
|
+
# - #[]=
|
61
|
+
# - #delete
|
62
|
+
# - #delete_if
|
63
|
+
# - #each
|
64
|
+
# - #values_at
|
65
|
+
#
|
66
|
+
# === \Row Mode
|
67
|
+
#
|
68
|
+
# Set a table to row mode with method #by_row!:
|
69
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
70
|
+
# table = CSV.parse(source, headers: true)
|
71
|
+
# table.by_row! # => #<CSV::Table mode:row row_count:4>
|
72
|
+
#
|
73
|
+
# Specify a single row by an \Integer index:
|
74
|
+
# # Get a row.
|
75
|
+
# table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
|
76
|
+
# # Set a row, then get it.
|
77
|
+
# table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
|
78
|
+
# table[1] # => #<CSV::Row "Name":"bam" "Value":3>
|
79
|
+
#
|
80
|
+
# Specify a sequence of rows by a \Range:
|
81
|
+
# # Get rows.
|
82
|
+
# table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
|
83
|
+
# # Set rows, then get them.
|
84
|
+
# table[1..2] = [
|
85
|
+
# CSV::Row.new(['Name', 'Value'], ['bat', 4]),
|
86
|
+
# CSV::Row.new(['Name', 'Value'], ['bad', 5]),
|
87
|
+
# ]
|
88
|
+
# table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
|
89
|
+
#
|
90
|
+
# === Column Mode
|
91
|
+
#
|
92
|
+
# Set a table to column mode with method #by_col!:
|
93
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
94
|
+
# table = CSV.parse(source, headers: true)
|
95
|
+
# table.by_col! # => #<CSV::Table mode:col row_count:4>
|
96
|
+
#
|
97
|
+
# Specify a column by an \Integer index:
|
98
|
+
# # Get a column.
|
99
|
+
# table[0]
|
100
|
+
# # Set a column, then get it.
|
101
|
+
# table[0] = ['FOO', 'BAR', 'BAZ']
|
102
|
+
# table[0] # => ["FOO", "BAR", "BAZ"]
|
103
|
+
#
|
104
|
+
# Specify a column by its \String header:
|
105
|
+
# # Get a column.
|
106
|
+
# table['Name'] # => ["FOO", "BAR", "BAZ"]
|
107
|
+
# # Set a column, then get it.
|
108
|
+
# table['Name'] = ['Foo', 'Bar', 'Baz']
|
109
|
+
# table['Name'] # => ["Foo", "Bar", "Baz"]
|
110
|
+
#
|
111
|
+
# === Mixed Mode
|
112
|
+
#
|
113
|
+
# In mixed mode, you can refer to either rows or columns:
|
114
|
+
# - An \Integer index refers to a row.
|
115
|
+
# - A \Range index refers to multiple rows.
|
116
|
+
# - A \String index refers to a column.
|
117
|
+
#
|
118
|
+
# Set a table to mixed mode with method #by_col_or_row!:
|
119
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
120
|
+
# table = CSV.parse(source, headers: true)
|
121
|
+
# table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
|
122
|
+
#
|
123
|
+
# Specify a single row by an \Integer index:
|
124
|
+
# # Get a row.
|
125
|
+
# table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
|
126
|
+
# # Set a row, then get it.
|
127
|
+
# table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
|
128
|
+
# table[1] # => #<CSV::Row "Name":"bam" "Value":3>
|
129
|
+
#
|
130
|
+
# Specify a sequence of rows by a \Range:
|
131
|
+
# # Get rows.
|
132
|
+
# table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
|
133
|
+
# # Set rows, then get them.
|
134
|
+
# table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4])
|
135
|
+
# table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5])
|
136
|
+
# table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
|
137
|
+
#
|
138
|
+
# Specify a column by its \String header:
|
139
|
+
# # Get a column.
|
140
|
+
# table['Name'] # => ["foo", "bat", "bad"]
|
141
|
+
# # Set a column, then get it.
|
142
|
+
# table['Name'] = ['Foo', 'Bar', 'Baz']
|
143
|
+
# table['Name'] # => ["Foo", "Bar", "Baz"]
|
14
144
|
class Table
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
145
|
+
# :call-seq:
|
146
|
+
# CSV::Table.new(array_of_rows, headers = nil)
|
147
|
+
#
|
148
|
+
# Returns a new \CSV::Table object.
|
149
|
+
#
|
150
|
+
# - Argument +array_of_rows+ must be an \Array of CSV::Row objects.
|
151
|
+
# - Argument +headers+, if given, may be an \Array of Strings.
|
152
|
+
#
|
153
|
+
# ---
|
154
|
+
#
|
155
|
+
# Create an empty \CSV::Table object:
|
156
|
+
# table = CSV::Table.new([])
|
157
|
+
# table # => #<CSV::Table mode:col_or_row row_count:1>
|
158
|
+
#
|
159
|
+
# Create a non-empty \CSV::Table object:
|
160
|
+
# rows = [
|
161
|
+
# CSV::Row.new([], []),
|
162
|
+
# CSV::Row.new([], []),
|
163
|
+
# CSV::Row.new([], []),
|
164
|
+
# ]
|
165
|
+
# table = CSV::Table.new(rows)
|
166
|
+
# table # => #<CSV::Table mode:col_or_row row_count:4>
|
167
|
+
#
|
168
|
+
# ---
|
169
|
+
#
|
170
|
+
# If argument +headers+ is an \Array of Strings,
|
171
|
+
# those Strings become the table's headers:
|
172
|
+
# table = CSV::Table.new([], headers: ['Name', 'Age'])
|
173
|
+
# table.headers # => ["Name", "Age"]
|
174
|
+
#
|
175
|
+
# If argument +headers+ is not given and the table has rows,
|
176
|
+
# the headers are taken from the first row:
|
177
|
+
# rows = [
|
178
|
+
# CSV::Row.new(['Foo', 'Bar'], []),
|
179
|
+
# CSV::Row.new(['foo', 'bar'], []),
|
180
|
+
# CSV::Row.new(['FOO', 'BAR'], []),
|
181
|
+
# ]
|
182
|
+
# table = CSV::Table.new(rows)
|
183
|
+
# table.headers # => ["Foo", "Bar"]
|
184
|
+
#
|
185
|
+
# If argument +headers+ is not given and the table is empty (has no rows),
|
186
|
+
# the headers are also empty:
|
187
|
+
# table = CSV::Table.new([])
|
188
|
+
# table.headers # => []
|
189
|
+
#
|
190
|
+
# ---
|
191
|
+
#
|
192
|
+
# Raises an exception if argument +array_of_rows+ is not an \Array object:
|
193
|
+
# # Raises NoMethodError (undefined method `first' for :foo:Symbol):
|
194
|
+
# CSV::Table.new(:foo)
|
195
|
+
#
|
196
|
+
# Raises an exception if an element of +array_of_rows+ is not a \CSV::Table object:
|
197
|
+
# # Raises NoMethodError (undefined method `headers' for :foo:Symbol):
|
198
|
+
# CSV::Table.new([:foo])
|
31
199
|
def initialize(array_of_rows, headers: nil)
|
32
200
|
@table = array_of_rows
|
33
201
|
@headers = headers
|
@@ -54,88 +222,141 @@ class CSV
|
|
54
222
|
extend Forwardable
|
55
223
|
def_delegators :@table, :empty?, :length, :size
|
56
224
|
|
225
|
+
# :call-seq:
|
226
|
+
# table.by_col
|
57
227
|
#
|
58
|
-
# Returns a duplicate
|
59
|
-
#
|
60
|
-
#
|
228
|
+
# Returns a duplicate of +self+, in column mode
|
229
|
+
# (see {Column Mode}[#class-CSV::Table-label-Column+Mode]):
|
230
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
231
|
+
# table = CSV.parse(source, headers: true)
|
232
|
+
# table.mode # => :col_or_row
|
233
|
+
# dup_table = table.by_col
|
234
|
+
# dup_table.mode # => :col
|
235
|
+
# dup_table.equal?(table) # => false # It's a dup
|
61
236
|
#
|
62
|
-
# This
|
63
|
-
#
|
64
|
-
#
|
237
|
+
# This may be used to chain method calls without changing the mode
|
238
|
+
# (but also will affect performance and memory usage):
|
239
|
+
# dup_table.by_col['Name']
|
65
240
|
#
|
241
|
+
# Also note that changes to the duplicate table will not affect the original.
|
66
242
|
def by_col
|
67
243
|
self.class.new(@table.dup).by_col!
|
68
244
|
end
|
69
245
|
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
246
|
+
# :call-seq:
|
247
|
+
# table.by_col!
|
248
|
+
#
|
249
|
+
# Sets the mode for +self+ to column mode
|
250
|
+
# (see {Column Mode}[#class-CSV::Table-label-Column+Mode]); returns +self+:
|
251
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
252
|
+
# table = CSV.parse(source, headers: true)
|
253
|
+
# table.mode # => :col_or_row
|
254
|
+
# table1 = table.by_col!
|
255
|
+
# table.mode # => :col
|
256
|
+
# table1.equal?(table) # => true # Returned self
|
76
257
|
def by_col!
|
77
258
|
@mode = :col
|
78
259
|
|
79
260
|
self
|
80
261
|
end
|
81
262
|
|
263
|
+
# :call-seq:
|
264
|
+
# table.by_col_or_row
|
82
265
|
#
|
83
|
-
# Returns a duplicate
|
84
|
-
#
|
85
|
-
#
|
266
|
+
# Returns a duplicate of +self+, in mixed mode
|
267
|
+
# (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]):
|
268
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
269
|
+
# table = CSV.parse(source, headers: true).by_col!
|
270
|
+
# table.mode # => :col
|
271
|
+
# dup_table = table.by_col_or_row
|
272
|
+
# dup_table.mode # => :col_or_row
|
273
|
+
# dup_table.equal?(table) # => false # It's a dup
|
86
274
|
#
|
87
|
-
# This
|
88
|
-
#
|
89
|
-
#
|
275
|
+
# This may be used to chain method calls without changing the mode
|
276
|
+
# (but also will affect performance and memory usage):
|
277
|
+
# dup_table.by_col_or_row['Name']
|
90
278
|
#
|
279
|
+
# Also note that changes to the duplicate table will not affect the original.
|
91
280
|
def by_col_or_row
|
92
281
|
self.class.new(@table.dup).by_col_or_row!
|
93
282
|
end
|
94
283
|
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
# the mode
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
284
|
+
# :call-seq:
|
285
|
+
# table.by_col_or_row!
|
286
|
+
#
|
287
|
+
# Sets the mode for +self+ to mixed mode
|
288
|
+
# (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]); returns +self+:
|
289
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
290
|
+
# table = CSV.parse(source, headers: true).by_col!
|
291
|
+
# table.mode # => :col
|
292
|
+
# table1 = table.by_col_or_row!
|
293
|
+
# table.mode # => :col_or_row
|
294
|
+
# table1.equal?(table) # => true # Returned self
|
103
295
|
def by_col_or_row!
|
104
296
|
@mode = :col_or_row
|
105
297
|
|
106
298
|
self
|
107
299
|
end
|
108
300
|
|
301
|
+
# :call-seq:
|
302
|
+
# table.by_row
|
109
303
|
#
|
110
|
-
# Returns a duplicate
|
111
|
-
#
|
112
|
-
#
|
304
|
+
# Returns a duplicate of +self+, in row mode
|
305
|
+
# (see {Row Mode}[#class-CSV::Table-label-Row+Mode]):
|
306
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
307
|
+
# table = CSV.parse(source, headers: true)
|
308
|
+
# table.mode # => :col_or_row
|
309
|
+
# dup_table = table.by_row
|
310
|
+
# dup_table.mode # => :row
|
311
|
+
# dup_table.equal?(table) # => false # It's a dup
|
113
312
|
#
|
114
|
-
# This
|
115
|
-
#
|
116
|
-
#
|
313
|
+
# This may be used to chain method calls without changing the mode
|
314
|
+
# (but also will affect performance and memory usage):
|
315
|
+
# dup_table.by_row[1]
|
117
316
|
#
|
317
|
+
# Also note that changes to the duplicate table will not affect the original.
|
118
318
|
def by_row
|
119
319
|
self.class.new(@table.dup).by_row!
|
120
320
|
end
|
121
321
|
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
322
|
+
# :call-seq:
|
323
|
+
# table.by_row!
|
324
|
+
#
|
325
|
+
# Sets the mode for +self+ to row mode
|
326
|
+
# (see {Row Mode}[#class-CSV::Table-label-Row+Mode]); returns +self+:
|
327
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
328
|
+
# table = CSV.parse(source, headers: true)
|
329
|
+
# table.mode # => :col_or_row
|
330
|
+
# table1 = table.by_row!
|
331
|
+
# table.mode # => :row
|
332
|
+
# table1.equal?(table) # => true # Returned self
|
128
333
|
def by_row!
|
129
334
|
@mode = :row
|
130
335
|
|
131
336
|
self
|
132
337
|
end
|
133
338
|
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
339
|
+
# :call-seq:
|
340
|
+
# table.headers
|
341
|
+
#
|
342
|
+
# Returns a new \Array containing the \String headers for the table.
|
343
|
+
#
|
344
|
+
# If the table is not empty, returns the headers from the first row:
|
345
|
+
# rows = [
|
346
|
+
# CSV::Row.new(['Foo', 'Bar'], []),
|
347
|
+
# CSV::Row.new(['FOO', 'BAR'], []),
|
348
|
+
# CSV::Row.new(['foo', 'bar'], []),
|
349
|
+
# ]
|
350
|
+
# table = CSV::Table.new(rows)
|
351
|
+
# table.headers # => ["Foo", "Bar"]
|
352
|
+
# table.delete(0)
|
353
|
+
# table.headers # => ["FOO", "BAR"]
|
354
|
+
# table.delete(0)
|
355
|
+
# table.headers # => ["foo", "bar"]
|
356
|
+
#
|
357
|
+
# If the table is empty, returns a copy of the headers in the table itself:
|
358
|
+
# table.delete(0)
|
359
|
+
# table.headers # => ["Foo", "Bar"]
|
139
360
|
def headers
|
140
361
|
if @table.empty?
|
141
362
|
@headers.dup
|
data/lib/csv/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Edward Gray II
|
@@ -9,22 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: stringio
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: 0.1.3
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: 0.1.3
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: bundler
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,28 +83,28 @@ files:
|
|
97
83
|
- LICENSE.txt
|
98
84
|
- NEWS.md
|
99
85
|
- README.md
|
100
|
-
- doc/arguments/io.rdoc
|
101
|
-
- doc/options/common/col_sep.rdoc
|
102
|
-
- doc/options/common/quote_char.rdoc
|
103
|
-
- doc/options/common/row_sep.rdoc
|
104
|
-
- doc/options/generating/force_quotes.rdoc
|
105
|
-
- doc/options/generating/quote_empty.rdoc
|
106
|
-
- doc/options/generating/write_converters.rdoc
|
107
|
-
- doc/options/generating/write_empty_value.rdoc
|
108
|
-
- doc/options/generating/write_headers.rdoc
|
109
|
-
- doc/options/generating/write_nil_value.rdoc
|
110
|
-
- doc/options/parsing/converters.rdoc
|
111
|
-
- doc/options/parsing/empty_value.rdoc
|
112
|
-
- doc/options/parsing/field_size_limit.rdoc
|
113
|
-
- doc/options/parsing/header_converters.rdoc
|
114
|
-
- doc/options/parsing/headers.rdoc
|
115
|
-
- doc/options/parsing/liberal_parsing.rdoc
|
116
|
-
- doc/options/parsing/nil_value.rdoc
|
117
|
-
- doc/options/parsing/return_headers.rdoc
|
118
|
-
- doc/options/parsing/skip_blanks.rdoc
|
119
|
-
- doc/options/parsing/skip_lines.rdoc
|
120
|
-
- doc/options/parsing/strip.rdoc
|
121
|
-
- doc/options/parsing/unconverted_fields.rdoc
|
86
|
+
- doc/csv/arguments/io.rdoc
|
87
|
+
- doc/csv/options/common/col_sep.rdoc
|
88
|
+
- doc/csv/options/common/quote_char.rdoc
|
89
|
+
- doc/csv/options/common/row_sep.rdoc
|
90
|
+
- doc/csv/options/generating/force_quotes.rdoc
|
91
|
+
- doc/csv/options/generating/quote_empty.rdoc
|
92
|
+
- doc/csv/options/generating/write_converters.rdoc
|
93
|
+
- doc/csv/options/generating/write_empty_value.rdoc
|
94
|
+
- doc/csv/options/generating/write_headers.rdoc
|
95
|
+
- doc/csv/options/generating/write_nil_value.rdoc
|
96
|
+
- doc/csv/options/parsing/converters.rdoc
|
97
|
+
- doc/csv/options/parsing/empty_value.rdoc
|
98
|
+
- doc/csv/options/parsing/field_size_limit.rdoc
|
99
|
+
- doc/csv/options/parsing/header_converters.rdoc
|
100
|
+
- doc/csv/options/parsing/headers.rdoc
|
101
|
+
- doc/csv/options/parsing/liberal_parsing.rdoc
|
102
|
+
- doc/csv/options/parsing/nil_value.rdoc
|
103
|
+
- doc/csv/options/parsing/return_headers.rdoc
|
104
|
+
- doc/csv/options/parsing/skip_blanks.rdoc
|
105
|
+
- doc/csv/options/parsing/skip_lines.rdoc
|
106
|
+
- doc/csv/options/parsing/strip.rdoc
|
107
|
+
- doc/csv/options/parsing/unconverted_fields.rdoc
|
122
108
|
- lib/csv.rb
|
123
109
|
- lib/csv/core_ext/array.rb
|
124
110
|
- lib/csv/core_ext/string.rb
|
@@ -144,14 +130,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
130
|
requirements:
|
145
131
|
- - ">="
|
146
132
|
- !ruby/object:Gem::Version
|
147
|
-
version: 2.
|
133
|
+
version: 2.5.0
|
148
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
135
|
requirements:
|
150
136
|
- - ">="
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: '0'
|
153
139
|
requirements: []
|
154
|
-
rubygems_version: 3.2.0.
|
140
|
+
rubygems_version: 3.2.0.rc.1
|
155
141
|
signing_key:
|
156
142
|
specification_version: 4
|
157
143
|
summary: CSV Reading and Writing
|