csv 3.1.9 → 3.3.2
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 +4 -4
- data/NEWS.md +361 -0
- data/README.md +3 -6
- data/doc/csv/options/generating/write_headers.rdoc +1 -1
- data/doc/csv/options/parsing/liberal_parsing.rdoc +21 -2
- data/doc/csv/recipes/filtering.rdoc +85 -17
- data/doc/csv/recipes/generating.rdoc +2 -2
- data/doc/csv/recipes/parsing.rdoc +16 -7
- data/lib/csv/core_ext/array.rb +1 -1
- data/lib/csv/core_ext/string.rb +1 -1
- data/lib/csv/fields_converter.rb +16 -4
- data/lib/csv/input_record_separator.rb +18 -0
- data/lib/csv/parser.rb +263 -113
- data/lib/csv/row.rb +23 -1
- data/lib/csv/table.rb +18 -7
- data/lib/csv/version.rb +1 -1
- data/lib/csv/writer.rb +6 -6
- data/lib/csv.rb +535 -188
- metadata +9 -66
- data/lib/csv/delete_suffix.rb +0 -18
- data/lib/csv/match_p.rb +0 -20
|
@@ -45,6 +45,7 @@ All code snippets on this page assume that the following has been executed:
|
|
|
45
45
|
- {Recipe: Convert Fields to Numerics}[#label-Recipe-3A+Convert+Fields+to+Numerics]
|
|
46
46
|
- {Recipe: Convert Fields to Dates}[#label-Recipe-3A+Convert+Fields+to+Dates]
|
|
47
47
|
- {Recipe: Convert Fields to DateTimes}[#label-Recipe-3A+Convert+Fields+to+DateTimes]
|
|
48
|
+
- {Recipe: Convert Fields to Times}[#label-Recipe-3A+Convert+Fields+to+Times]
|
|
48
49
|
- {Recipe: Convert Assorted Fields to Objects}[#label-Recipe-3A+Convert+Assorted+Fields+to+Objects]
|
|
49
50
|
- {Recipe: Convert Fields to Other Objects}[#label-Recipe-3A+Convert+Fields+to+Other+Objects]
|
|
50
51
|
- {Recipe: Filter Field Strings}[#label-Recipe-3A+Filter+Field+Strings]
|
|
@@ -83,7 +84,7 @@ Use instance method CSV#each with option +headers+ to read a source \String one
|
|
|
83
84
|
CSV.new(string, headers: true).each do |row|
|
|
84
85
|
p row
|
|
85
86
|
end
|
|
86
|
-
|
|
87
|
+
Output:
|
|
87
88
|
#<CSV::Row "Name":"foo" "Value":"0">
|
|
88
89
|
#<CSV::Row "Name":"bar" "Value":"1">
|
|
89
90
|
#<CSV::Row "Name":"baz" "Value":"2">
|
|
@@ -110,7 +111,7 @@ You can parse \CSV data from a \File, with or without headers.
|
|
|
110
111
|
|
|
111
112
|
===== Recipe: Parse from \File with Headers
|
|
112
113
|
|
|
113
|
-
Use
|
|
114
|
+
Use class method CSV.read with option +headers+ to read a file all at once:
|
|
114
115
|
string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
|
115
116
|
path = 't.csv'
|
|
116
117
|
File.write(path, string)
|
|
@@ -191,7 +192,7 @@ Output:
|
|
|
191
192
|
=== RFC 4180 Compliance
|
|
192
193
|
|
|
193
194
|
By default, \CSV parses data that is compliant with
|
|
194
|
-
{RFC 4180}[https://
|
|
195
|
+
{RFC 4180}[https://www.rfc-editor.org/rfc/rfc4180]
|
|
195
196
|
with respect to:
|
|
196
197
|
- Row separator.
|
|
197
198
|
- Column separator.
|
|
@@ -339,6 +340,7 @@ There are built-in field converters for converting to objects of certain classes
|
|
|
339
340
|
- \Integer
|
|
340
341
|
- \Date
|
|
341
342
|
- \DateTime
|
|
343
|
+
- \Time
|
|
342
344
|
|
|
343
345
|
Other built-in field converters include:
|
|
344
346
|
- +:numeric+: converts to \Integer and \Float.
|
|
@@ -381,6 +383,13 @@ Convert fields to \DateTime objects using built-in converter +:date_time+:
|
|
|
381
383
|
parsed = CSV.parse(source, headers: true, converters: :date_time)
|
|
382
384
|
parsed.map {|row| row['DateTime'].class} # => [DateTime, DateTime, DateTime]
|
|
383
385
|
|
|
386
|
+
===== Recipe: Convert Fields to Times
|
|
387
|
+
|
|
388
|
+
Convert fields to \Time objects using built-in converter +:time+:
|
|
389
|
+
source = "Name,Time\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2020-05-07T14:59:00-05:00\n"
|
|
390
|
+
parsed = CSV.parse(source, headers: true, converters: :time)
|
|
391
|
+
parsed.map {|row| row['Time'].class} # => [Time, Time, Time]
|
|
392
|
+
|
|
384
393
|
===== Recipe: Convert Assorted Fields to Objects
|
|
385
394
|
|
|
386
395
|
Convert assorted fields to objects using built-in converter +:all+:
|
|
@@ -431,7 +440,7 @@ You can use multiple field converters in either of these ways:
|
|
|
431
440
|
|
|
432
441
|
===== Recipe: Specify Multiple Field Converters in Option +:converters+
|
|
433
442
|
|
|
434
|
-
Apply multiple field converters by specifying them in option +:
|
|
443
|
+
Apply multiple field converters by specifying them in option +:converters+:
|
|
435
444
|
source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n"
|
|
436
445
|
parsed = CSV.parse(source, headers: true, converters: [:integer, :float])
|
|
437
446
|
parsed['Value'] # => [0, 1.0, 2.0]
|
|
@@ -500,7 +509,7 @@ You can use multiple header converters in either of these ways:
|
|
|
500
509
|
|
|
501
510
|
===== Recipe: Specify Multiple Header Converters in Option :header_converters
|
|
502
511
|
|
|
503
|
-
Apply multiple header converters by specifying them in option +:
|
|
512
|
+
Apply multiple header converters by specifying them in option +:header_converters+:
|
|
504
513
|
source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n"
|
|
505
514
|
parsed = CSV.parse(source, headers: true, header_converters: [:downcase, :symbol])
|
|
506
515
|
parsed.headers # => [:name, :value]
|
|
@@ -520,7 +529,7 @@ Apply multiple header converters by defining and registering a custom header con
|
|
|
520
529
|
To capture unconverted field values, use option +:unconverted_fields+:
|
|
521
530
|
source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
|
522
531
|
parsed = CSV.parse(source, converters: :integer, unconverted_fields: true)
|
|
523
|
-
parsed # => [["
|
|
532
|
+
parsed # => [["Name", "Value"], ["foo", 0], ["bar", 1], ["baz", 2]]
|
|
524
533
|
parsed.each {|row| p row.unconverted_fields }
|
|
525
534
|
Output:
|
|
526
535
|
["Name", "Value"]
|
|
@@ -542,4 +551,4 @@ Output:
|
|
|
542
551
|
#<struct CSV::FieldInfo index=0, line=2, header=nil>
|
|
543
552
|
#<struct CSV::FieldInfo index=1, line=2, header=nil>
|
|
544
553
|
#<struct CSV::FieldInfo index=0, line=3, header=nil>
|
|
545
|
-
#<struct CSV::FieldInfo index=1, line=3, header=nil>
|
|
554
|
+
#<struct CSV::FieldInfo index=1, line=3, header=nil>
|
data/lib/csv/core_ext/array.rb
CHANGED
data/lib/csv/core_ext/string.rb
CHANGED
data/lib/csv/fields_converter.rb
CHANGED
|
@@ -4,6 +4,13 @@ class CSV
|
|
|
4
4
|
# Note: Don't use this class directly. This is an internal class.
|
|
5
5
|
class FieldsConverter
|
|
6
6
|
include Enumerable
|
|
7
|
+
|
|
8
|
+
NO_QUOTED_FIELDS = [] # :nodoc:
|
|
9
|
+
def NO_QUOTED_FIELDS.[](_index)
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
NO_QUOTED_FIELDS.freeze
|
|
13
|
+
|
|
7
14
|
#
|
|
8
15
|
# A CSV::FieldsConverter is a data structure for storing the
|
|
9
16
|
# fields converter properties to be passed as a parameter
|
|
@@ -16,7 +23,7 @@ class CSV
|
|
|
16
23
|
@empty_value = options[:empty_value]
|
|
17
24
|
@empty_value_is_empty_string = (@empty_value == "")
|
|
18
25
|
@accept_nil = options[:accept_nil]
|
|
19
|
-
@
|
|
26
|
+
@builtin_converters_name = options[:builtin_converters_name]
|
|
20
27
|
@need_static_convert = need_static_convert?
|
|
21
28
|
end
|
|
22
29
|
|
|
@@ -24,7 +31,7 @@ class CSV
|
|
|
24
31
|
if name.nil? # custom converter
|
|
25
32
|
@converters << converter
|
|
26
33
|
else # named converter
|
|
27
|
-
combo =
|
|
34
|
+
combo = builtin_converters[name]
|
|
28
35
|
case combo
|
|
29
36
|
when Array # combo converter
|
|
30
37
|
combo.each do |sub_name|
|
|
@@ -44,7 +51,7 @@ class CSV
|
|
|
44
51
|
@converters.empty?
|
|
45
52
|
end
|
|
46
53
|
|
|
47
|
-
def convert(fields, headers, lineno)
|
|
54
|
+
def convert(fields, headers, lineno, quoted_fields=NO_QUOTED_FIELDS)
|
|
48
55
|
return fields unless need_convert?
|
|
49
56
|
|
|
50
57
|
fields.collect.with_index do |field, index|
|
|
@@ -63,7 +70,8 @@ class CSV
|
|
|
63
70
|
else
|
|
64
71
|
header = nil
|
|
65
72
|
end
|
|
66
|
-
|
|
73
|
+
quoted = quoted_fields[index]
|
|
74
|
+
field = converter[field, FieldInfo.new(index, lineno, header, quoted)]
|
|
67
75
|
end
|
|
68
76
|
break unless field.is_a?(String) # short-circuit pipeline for speed
|
|
69
77
|
end
|
|
@@ -80,5 +88,9 @@ class CSV
|
|
|
80
88
|
@need_static_convert or
|
|
81
89
|
(not @converters.empty?)
|
|
82
90
|
end
|
|
91
|
+
|
|
92
|
+
def builtin_converters
|
|
93
|
+
@builtin_converters ||= ::CSV.const_get(@builtin_converters_name)
|
|
94
|
+
end
|
|
83
95
|
end
|
|
84
96
|
end
|