rbs 2.0.0 → 2.2.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.
Files changed (208) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +34 -0
  3. data/.github/workflows/ruby.yml +5 -0
  4. data/CHANGELOG.md +82 -0
  5. data/README.md +6 -1
  6. data/Rakefile +56 -21
  7. data/core/array.rbs +2866 -1086
  8. data/core/basic_object.rbs +150 -30
  9. data/core/binding.rbs +33 -0
  10. data/core/builtin.rbs +4 -4
  11. data/core/class.rbs +43 -5
  12. data/core/comparable.rbs +57 -0
  13. data/core/complex.rbs +170 -4
  14. data/core/constants.rbs +51 -0
  15. data/core/deprecated.rbs +7 -0
  16. data/core/dir.rbs +305 -20
  17. data/core/encoding.rbs +1214 -77
  18. data/core/enumerable.rbs +2173 -234
  19. data/core/enumerator.rbs +448 -182
  20. data/core/env.rbs +448 -1
  21. data/core/errno.rbs +1 -10
  22. data/core/errors.rbs +152 -2
  23. data/core/exception.rbs +201 -127
  24. data/core/false_class.rbs +27 -0
  25. data/core/fiber.rbs +118 -37
  26. data/core/fiber_error.rbs +8 -9
  27. data/core/file.rbs +1060 -142
  28. data/core/file_test.rbs +287 -32
  29. data/core/float.rbs +776 -300
  30. data/core/gc.rbs +185 -34
  31. data/core/global_variables.rbs +5 -1
  32. data/core/hash.rbs +1582 -649
  33. data/core/integer.rbs +974 -204
  34. data/core/io/buffer.rbs +710 -0
  35. data/core/io/wait.rbs +29 -8
  36. data/core/io.rbs +2438 -417
  37. data/core/kernel.rbs +2319 -318
  38. data/core/marshal.rbs +37 -2
  39. data/core/match_data.rbs +123 -6
  40. data/core/math.rbs +126 -6
  41. data/core/method.rbs +226 -102
  42. data/core/module.rbs +421 -45
  43. data/core/nil_class.rbs +64 -0
  44. data/core/numeric.rbs +620 -142
  45. data/core/object.rbs +453 -81
  46. data/core/object_space.rbs +92 -2
  47. data/core/proc.rbs +482 -285
  48. data/core/process.rbs +443 -34
  49. data/core/ractor.rbs +232 -9
  50. data/core/random.rbs +151 -52
  51. data/core/range.rbs +885 -160
  52. data/core/rational.rbs +122 -6
  53. data/core/rb_config.rbs +14 -4
  54. data/core/refinement.rbs +44 -0
  55. data/core/regexp.rbs +156 -14
  56. data/core/ruby_vm.rbs +42 -3
  57. data/core/signal.rbs +78 -39
  58. data/core/string.rbs +2123 -567
  59. data/core/string_io.rbs +204 -0
  60. data/core/struct.rbs +283 -28
  61. data/core/symbol.rbs +304 -30
  62. data/core/thread.rbs +1288 -688
  63. data/core/thread_group.rbs +66 -10
  64. data/core/time.rbs +643 -217
  65. data/core/trace_point.rbs +100 -12
  66. data/core/true_class.rbs +24 -0
  67. data/core/unbound_method.rbs +73 -7
  68. data/core/warning.rbs +37 -12
  69. data/docs/CONTRIBUTING.md +40 -34
  70. data/docs/stdlib.md +3 -102
  71. data/docs/syntax.md +54 -11
  72. data/ext/rbs_extension/extconf.rb +1 -0
  73. data/ext/rbs_extension/lexer.h +5 -0
  74. data/ext/rbs_extension/lexstate.c +6 -0
  75. data/ext/rbs_extension/parser.c +85 -10
  76. data/ext/rbs_extension/ruby_objs.c +4 -2
  77. data/ext/rbs_extension/ruby_objs.h +2 -2
  78. data/goodcheck.yml +0 -11
  79. data/lib/rbs/annotate/annotations.rb +197 -0
  80. data/lib/rbs/annotate/formatter.rb +80 -0
  81. data/lib/rbs/annotate/rdoc_annotator.rb +398 -0
  82. data/lib/rbs/annotate/rdoc_source.rb +120 -0
  83. data/lib/rbs/annotate.rb +6 -0
  84. data/lib/rbs/ast/members.rb +21 -13
  85. data/lib/rbs/buffer.rb +17 -11
  86. data/lib/rbs/cli.rb +48 -1
  87. data/lib/rbs/definition_builder/method_builder.rb +28 -16
  88. data/lib/rbs/definition_builder.rb +6 -2
  89. data/lib/rbs/environment.rb +8 -4
  90. data/lib/rbs/location_aux.rb +12 -0
  91. data/lib/rbs/namespace.rb +1 -1
  92. data/lib/rbs/prototype/rb.rb +12 -0
  93. data/lib/rbs/type_alias_regularity.rb +6 -4
  94. data/lib/rbs/type_name.rb +1 -1
  95. data/lib/rbs/types.rb +1 -1
  96. data/lib/rbs/validator.rb +6 -0
  97. data/lib/rbs/version.rb +1 -1
  98. data/lib/rbs/writer.rb +54 -4
  99. data/lib/rbs.rb +0 -2
  100. data/schema/typeParam.json +3 -3
  101. data/sig/annotate/annotations.rbs +102 -0
  102. data/sig/annotate/formatter.rbs +24 -0
  103. data/sig/annotate/rdoc_annotater.rbs +82 -0
  104. data/sig/annotate/rdoc_source.rbs +30 -0
  105. data/sig/buffer.rbs +6 -2
  106. data/sig/cli.rbs +2 -0
  107. data/sig/collection/{collections.rbs → sources.rbs} +0 -0
  108. data/sig/location.rbs +6 -0
  109. data/sig/members.rbs +24 -18
  110. data/sig/method_builder.rbs +5 -4
  111. data/sig/method_types.rbs +5 -1
  112. data/sig/polyfill.rbs +78 -0
  113. data/sig/validator.rbs +3 -1
  114. data/sig/writer.rbs +79 -2
  115. data/stdlib/abbrev/0/abbrev.rbs +6 -0
  116. data/stdlib/abbrev/0/array.rbs +26 -0
  117. data/stdlib/base64/0/base64.rbs +31 -0
  118. data/stdlib/benchmark/0/benchmark.rbs +74 -3
  119. data/stdlib/bigdecimal/0/big_decimal.rbs +614 -165
  120. data/stdlib/bigdecimal-math/0/big_math.rbs +41 -64
  121. data/stdlib/cgi/0/core.rbs +649 -21
  122. data/stdlib/coverage/0/coverage.rbs +164 -2
  123. data/stdlib/csv/0/csv.rbs +2862 -398
  124. data/stdlib/date/0/date.rbs +483 -25
  125. data/stdlib/date/0/date_time.rbs +187 -12
  126. data/stdlib/dbm/0/dbm.rbs +152 -17
  127. data/stdlib/digest/0/digest.rbs +146 -0
  128. data/stdlib/erb/0/erb.rbs +65 -245
  129. data/stdlib/fiber/0/fiber.rbs +73 -91
  130. data/stdlib/fileutils/0/fileutils.rbs +301 -1
  131. data/stdlib/find/0/find.rbs +9 -0
  132. data/stdlib/forwardable/0/forwardable.rbs +65 -1
  133. data/stdlib/io-console/0/io-console.rbs +227 -15
  134. data/stdlib/ipaddr/0/ipaddr.rbs +161 -0
  135. data/stdlib/json/0/json.rbs +1147 -145
  136. data/stdlib/logger/0/formatter.rbs +24 -0
  137. data/stdlib/logger/0/log_device.rbs +64 -0
  138. data/stdlib/logger/0/logger.rbs +165 -13
  139. data/stdlib/logger/0/period.rbs +10 -0
  140. data/stdlib/logger/0/severity.rbs +26 -0
  141. data/stdlib/monitor/0/monitor.rbs +163 -0
  142. data/stdlib/mutex_m/0/mutex_m.rbs +35 -6
  143. data/stdlib/net-http/0/manifest.yaml +1 -0
  144. data/stdlib/net-http/0/net-http.rbs +1513 -683
  145. data/stdlib/nkf/0/nkf.rbs +372 -0
  146. data/stdlib/objspace/0/objspace.rbs +149 -90
  147. data/stdlib/openssl/0/openssl.rbs +8108 -71
  148. data/stdlib/optparse/0/optparse.rbs +487 -19
  149. data/stdlib/pathname/0/pathname.rbs +425 -124
  150. data/stdlib/prettyprint/0/prettyprint.rbs +120 -99
  151. data/stdlib/prime/0/integer-extension.rbs +20 -2
  152. data/stdlib/prime/0/prime.rbs +88 -21
  153. data/stdlib/pstore/0/pstore.rbs +102 -0
  154. data/stdlib/pty/0/pty.rbs +64 -14
  155. data/stdlib/resolv/0/resolv.rbs +420 -31
  156. data/stdlib/rubygems/0/basic_specification.rbs +4 -1
  157. data/stdlib/rubygems/0/config_file.rbs +33 -1
  158. data/stdlib/rubygems/0/dependency_installer.rbs +4 -3
  159. data/stdlib/rubygems/0/installer.rbs +13 -1
  160. data/stdlib/rubygems/0/path_support.rbs +4 -1
  161. data/stdlib/rubygems/0/platform.rbs +5 -1
  162. data/stdlib/rubygems/0/request_set.rbs +44 -2
  163. data/stdlib/rubygems/0/requirement.rbs +65 -2
  164. data/stdlib/rubygems/0/rubygems.rbs +407 -0
  165. data/stdlib/rubygems/0/source_list.rbs +13 -0
  166. data/stdlib/rubygems/0/specification.rbs +21 -1
  167. data/stdlib/rubygems/0/stream_ui.rbs +3 -1
  168. data/stdlib/rubygems/0/uninstaller.rbs +8 -1
  169. data/stdlib/rubygems/0/version.rbs +60 -157
  170. data/stdlib/securerandom/0/securerandom.rbs +44 -0
  171. data/stdlib/set/0/set.rbs +423 -109
  172. data/stdlib/shellwords/0/shellwords.rbs +55 -77
  173. data/stdlib/singleton/0/singleton.rbs +20 -0
  174. data/stdlib/socket/0/addrinfo.rbs +210 -9
  175. data/stdlib/socket/0/basic_socket.rbs +103 -11
  176. data/stdlib/socket/0/ip_socket.rbs +31 -9
  177. data/stdlib/socket/0/socket.rbs +586 -38
  178. data/stdlib/socket/0/tcp_server.rbs +22 -2
  179. data/stdlib/socket/0/tcp_socket.rbs +12 -1
  180. data/stdlib/socket/0/udp_socket.rbs +25 -2
  181. data/stdlib/socket/0/unix_server.rbs +22 -2
  182. data/stdlib/socket/0/unix_socket.rbs +45 -5
  183. data/stdlib/strscan/0/string_scanner.rbs +210 -9
  184. data/stdlib/tempfile/0/tempfile.rbs +58 -10
  185. data/stdlib/time/0/time.rbs +208 -116
  186. data/stdlib/timeout/0/timeout.rbs +10 -0
  187. data/stdlib/tmpdir/0/tmpdir.rbs +13 -4
  188. data/stdlib/tsort/0/cyclic.rbs +1 -0
  189. data/stdlib/tsort/0/interfaces.rbs +1 -0
  190. data/stdlib/tsort/0/tsort.rbs +42 -0
  191. data/stdlib/uri/0/common.rbs +57 -8
  192. data/stdlib/uri/0/file.rbs +55 -109
  193. data/stdlib/uri/0/ftp.rbs +6 -3
  194. data/stdlib/uri/0/generic.rbs +558 -329
  195. data/stdlib/uri/0/http.rbs +60 -114
  196. data/stdlib/uri/0/https.rbs +8 -102
  197. data/stdlib/uri/0/ldap.rbs +143 -137
  198. data/stdlib/uri/0/ldaps.rbs +8 -102
  199. data/stdlib/uri/0/mailto.rbs +3 -0
  200. data/stdlib/uri/0/rfc2396_parser.rbs +66 -26
  201. data/stdlib/uri/0/ws.rbs +6 -3
  202. data/stdlib/uri/0/wss.rbs +5 -3
  203. data/stdlib/yaml/0/dbm.rbs +151 -87
  204. data/stdlib/yaml/0/store.rbs +6 -0
  205. data/stdlib/zlib/0/zlib.rbs +90 -31
  206. metadata +18 -6
  207. data/lib/rbs/location.rb +0 -221
  208. data/sig/char_scanner.rbs +0 -9
data/stdlib/csv/0/csv.rbs CHANGED
@@ -1,122 +1,1611 @@
1
- # This class provides a complete interface to CSV files and data. It offers
2
- # tools to enable you to read and write to and from Strings or IO objects, as
3
- # needed.
1
+ # <!-- rdoc-file=lib/csv.rb -->
2
+ # ## CSV
3
+ # CSV (comma-separated variables) data is a text representation of a table:
4
+ # * A *row* *separator* delimits table rows. A common row separator is the
5
+ # newline character `"\n"`.
6
+ # * A *column* *separator* delimits fields in a row. A common column separator
7
+ # is the comma character `","`.
4
8
  #
5
- # The most generic interface of the library is:
6
9
  #
7
- # csv = CSV.new(string_or_io, **options)
10
+ # This CSV String, with row separator `"\n"` and column separator `","`, has
11
+ # three rows and two columns:
12
+ # "foo,0\nbar,1\nbaz,2\n"
8
13
  #
9
- # # Reading: IO object should be open for read
10
- # csv.read # => array of rows
11
- # # or
12
- # csv.each do |row|
13
- # # ...
14
+ # Despite the name CSV, a CSV representation can use different separators.
15
+ #
16
+ # For more about tables, see the Wikipedia article "[Table
17
+ # (information)](https://en.wikipedia.org/wiki/Table_(information))", especially
18
+ # its section "[Simple
19
+ # table](https://en.wikipedia.org/wiki/Table_(information)#Simple_table)"
20
+ #
21
+ # ## Class CSV
22
+ #
23
+ # Class CSV provides methods for:
24
+ # * Parsing CSV data from a String object, a File (via its file path), or an
25
+ # IO object.
26
+ # * Generating CSV data to a String object.
27
+ #
28
+ #
29
+ # To make CSV available:
30
+ # require 'csv'
31
+ #
32
+ # All examples here assume that this has been done.
33
+ #
34
+ # ## Keeping It Simple
35
+ #
36
+ # A CSV object has dozens of instance methods that offer fine-grained control of
37
+ # parsing and generating CSV data. For many needs, though, simpler approaches
38
+ # will do.
39
+ #
40
+ # This section summarizes the singleton methods in CSV that allow you to parse
41
+ # and generate without explicitly creating CSV objects. For details, follow the
42
+ # links.
43
+ #
44
+ # ### Simple Parsing
45
+ #
46
+ # Parsing methods commonly return either of:
47
+ # * An Array of Arrays of Strings:
48
+ # * The outer Array is the entire "table".
49
+ # * Each inner Array is a row.
50
+ # * Each String is a field.
51
+ #
52
+ # * A CSV::Table object. For details, see [\CSV with
53
+ # Headers](#class-CSV-label-CSV+with+Headers).
54
+ #
55
+ #
56
+ # #### Parsing a String
57
+ #
58
+ # The input to be parsed can be a string:
59
+ # string = "foo,0\nbar,1\nbaz,2\n"
60
+ #
61
+ # Method CSV.parse returns the entire CSV data:
62
+ # CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
63
+ #
64
+ # Method CSV.parse_line returns only the first row:
65
+ # CSV.parse_line(string) # => ["foo", "0"]
66
+ #
67
+ # CSV extends class String with instance method String#parse_csv, which also
68
+ # returns only the first row:
69
+ # string.parse_csv # => ["foo", "0"]
70
+ #
71
+ # #### Parsing Via a File Path
72
+ #
73
+ # The input to be parsed can be in a file:
74
+ # string = "foo,0\nbar,1\nbaz,2\n"
75
+ # path = 't.csv'
76
+ # File.write(path, string)
77
+ #
78
+ # Method CSV.read returns the entire CSV data:
79
+ # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
80
+ #
81
+ # Method CSV.foreach iterates, passing each row to the given block:
82
+ # CSV.foreach(path) do |row|
83
+ # p row
14
84
  # end
15
- # # or
16
- # row = csv.shift
17
85
  #
18
- # # Writing: IO object should be open for write
19
- # csv << row
86
+ # Output:
87
+ # ["foo", "0"]
88
+ # ["bar", "1"]
89
+ # ["baz", "2"]
90
+ #
91
+ # Method CSV.table returns the entire CSV data as a CSV::Table object:
92
+ # CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:3>
20
93
  #
21
- # There are several specialized class methods for one-statement reading or
22
- # writing, described in the Specialized Methods section.
94
+ # #### Parsing from an Open IO Stream
23
95
  #
24
- # If a String is passed into ::new, it is internally wrapped into a StringIO
25
- # object.
96
+ # The input to be parsed can be in an open IO stream:
26
97
  #
27
- # `options` can be used for specifying the particular CSV flavor (column
28
- # separators, row separators, value quoting and so on), and for data conversion,
29
- # see Data Conversion section for the description of the latter.
98
+ # Method CSV.read returns the entire CSV data:
99
+ # File.open(path) do |file|
100
+ # CSV.read(file)
101
+ # end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
30
102
  #
31
- # ## Specialized Methods
103
+ # As does method CSV.parse:
104
+ # File.open(path) do |file|
105
+ # CSV.parse(file)
106
+ # end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
32
107
  #
33
- # ### Reading
108
+ # Method CSV.parse_line returns only the first row:
109
+ # File.open(path) do |file|
110
+ # CSV.parse_line(file)
111
+ # end # => ["foo", "0"]
34
112
  #
35
- # # From a file: all at once
36
- # arr_of_rows = CSV.read("path/to/file.csv", **options)
37
- # # iterator-style:
38
- # CSV.foreach("path/to/file.csv", **options) do |row|
39
- # # ...
113
+ # Method CSV.foreach iterates, passing each row to the given block:
114
+ # File.open(path) do |file|
115
+ # CSV.foreach(file) do |row|
116
+ # p row
117
+ # end
40
118
  # end
41
119
  #
42
- # # From a string
43
- # arr_of_rows = CSV.parse("CSV,data,String", **options)
44
- # # or
45
- # CSV.parse("CSV,data,String", **options) do |row|
46
- # # ...
120
+ # Output:
121
+ # ["foo", "0"]
122
+ # ["bar", "1"]
123
+ # ["baz", "2"]
124
+ #
125
+ # Method CSV.table returns the entire CSV data as a CSV::Table object:
126
+ # File.open(path) do |file|
127
+ # CSV.table(file)
128
+ # end # => #<CSV::Table mode:col_or_row row_count:3>
129
+ #
130
+ # ### Simple Generating
131
+ #
132
+ # Method CSV.generate returns a String; this example uses method CSV#<< to
133
+ # append the rows that are to be generated:
134
+ # output_string = CSV.generate do |csv|
135
+ # csv << ['foo', 0]
136
+ # csv << ['bar', 1]
137
+ # csv << ['baz', 2]
47
138
  # end
139
+ # output_string # => "foo,0\nbar,1\nbaz,2\n"
48
140
  #
49
- # ### Writing
141
+ # Method CSV.generate_line returns a String containing the single row
142
+ # constructed from an Array:
143
+ # CSV.generate_line(['foo', '0']) # => "foo,0\n"
50
144
  #
51
- # # To a file
52
- # CSV.open("path/to/file.csv", "wb") do |csv|
53
- # csv << ["row", "of", "CSV", "data"]
54
- # csv << ["another", "row"]
55
- # # ...
145
+ # CSV extends class Array with instance method `Array#to_csv`, which forms an
146
+ # Array into a String:
147
+ # ['foo', '0'].to_csv # => "foo,0\n"
148
+ #
149
+ # ### "Filtering" CSV
150
+ #
151
+ # Method CSV.filter provides a Unix-style filter for CSV data. The input data is
152
+ # processed to form the output data:
153
+ # in_string = "foo,0\nbar,1\nbaz,2\n"
154
+ # out_string = ''
155
+ # CSV.filter(in_string, out_string) do |row|
156
+ # row[0] = row[0].upcase
157
+ # row[1] *= 4
56
158
  # end
159
+ # out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
160
+ #
161
+ # ## CSV Objects
162
+ #
163
+ # There are three ways to create a CSV object:
164
+ # * Method CSV.new returns a new CSV object.
165
+ # * Method CSV.instance returns a new or cached CSV object.
166
+ # * Method CSV() also returns a new or cached CSV object.
167
+ #
168
+ #
169
+ # ### Instance Methods
170
+ #
171
+ # CSV has three groups of instance methods:
172
+ # * Its own internally defined instance methods.
173
+ # * Methods included by module Enumerable.
174
+ # * Methods delegated to class IO. See below.
175
+ #
176
+ #
177
+ # #### Delegated Methods
178
+ #
179
+ # For convenience, a CSV object will delegate to many methods in class IO. (A
180
+ # few have wrapper "guard code" in CSV.) You may call:
181
+ # * IO#binmode
182
+ # * #binmode?
183
+ # * IO#close
184
+ # * IO#close_read
185
+ # * IO#close_write
186
+ # * IO#closed?
187
+ # * #eof
188
+ # * #eof?
189
+ # * IO#external_encoding
190
+ # * IO#fcntl
191
+ # * IO#fileno
192
+ # * #flock
193
+ # * IO#flush
194
+ # * IO#fsync
195
+ # * IO#internal_encoding
196
+ # * #ioctl
197
+ # * IO#isatty
198
+ # * #path
199
+ # * IO#pid
200
+ # * IO#pos
201
+ # * IO#pos=
202
+ # * IO#reopen
203
+ # * #rewind
204
+ # * IO#seek
205
+ # * #stat
206
+ # * IO#string
207
+ # * IO#sync
208
+ # * IO#sync=
209
+ # * IO#tell
210
+ # * #to_i
211
+ # * #to_io
212
+ # * IO#truncate
213
+ # * IO#tty?
214
+ #
215
+ #
216
+ # ### Options
217
+ #
218
+ # The default values for options are:
219
+ # DEFAULT_OPTIONS = {
220
+ # # For both parsing and generating.
221
+ # col_sep: ",",
222
+ # row_sep: :auto,
223
+ # quote_char: '"',
224
+ # # For parsing.
225
+ # field_size_limit: nil,
226
+ # converters: nil,
227
+ # unconverted_fields: nil,
228
+ # headers: false,
229
+ # return_headers: false,
230
+ # header_converters: nil,
231
+ # skip_blanks: false,
232
+ # skip_lines: nil,
233
+ # liberal_parsing: false,
234
+ # nil_value: nil,
235
+ # empty_value: "",
236
+ # strip: false,
237
+ # # For generating.
238
+ # write_headers: nil,
239
+ # quote_empty: true,
240
+ # force_quotes: false,
241
+ # write_converters: nil,
242
+ # write_nil_value: nil,
243
+ # write_empty_value: "",
244
+ # }
245
+ #
246
+ # #### Options for Parsing
247
+ #
248
+ # Options for parsing, described in detail below, include:
249
+ # * `row_sep`: Specifies the row separator; used to delimit rows.
250
+ # * `col_sep`: Specifies the column separator; used to delimit fields.
251
+ # * `quote_char`: Specifies the quote character; used to quote fields.
252
+ # * `field_size_limit`: Specifies the maximum field size allowed.
253
+ # * `converters`: Specifies the field converters to be used.
254
+ # * `unconverted_fields`: Specifies whether unconverted fields are to be
255
+ # available.
256
+ # * `headers`: Specifies whether data contains headers, or specifies the
257
+ # headers themselves.
258
+ # * `return_headers`: Specifies whether headers are to be returned.
259
+ # * `header_converters`: Specifies the header converters to be used.
260
+ # * `skip_blanks`: Specifies whether blanks lines are to be ignored.
261
+ # * `skip_lines`: Specifies how comments lines are to be recognized.
262
+ # * `strip`: Specifies whether leading and trailing whitespace are to be
263
+ # stripped from fields. This must be compatible with `col_sep`; if it is
264
+ # not, then an `ArgumentError` exception will be raised.
265
+ # * `liberal_parsing`: Specifies whether CSV should attempt to parse
266
+ # non-compliant data.
267
+ # * `nil_value`: Specifies the object that is to be substituted for each null
268
+ # (no-text) field.
269
+ # * `empty_value`: Specifies the object that is to be substituted for each
270
+ # empty field.
271
+ #
272
+ #
273
+ # ###### Option `row_sep`
274
+ #
275
+ # Specifies the row separator, a String or the Symbol `:auto` (see below), to be
276
+ # used for both parsing and generating.
277
+ #
278
+ # Default value:
279
+ # CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto
57
280
  #
58
- # # To a String
59
- # csv_string = CSV.generate do |csv|
60
- # csv << ["row", "of", "CSV", "data"]
61
- # csv << ["another", "row"]
62
- # # ...
281
+ # ---
282
+ #
283
+ # When `row_sep` is a String, that String becomes the row separator. The String
284
+ # will be transcoded into the data's Encoding before use.
285
+ #
286
+ # Using `"\n"`:
287
+ # row_sep = "\n"
288
+ # str = CSV.generate(row_sep: row_sep) do |csv|
289
+ # csv << [:foo, 0]
290
+ # csv << [:bar, 1]
291
+ # csv << [:baz, 2]
292
+ # end
293
+ # str # => "foo,0\nbar,1\nbaz,2\n"
294
+ # ary = CSV.parse(str)
295
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
296
+ #
297
+ # Using `|` (pipe):
298
+ # row_sep = '|'
299
+ # str = CSV.generate(row_sep: row_sep) do |csv|
300
+ # csv << [:foo, 0]
301
+ # csv << [:bar, 1]
302
+ # csv << [:baz, 2]
303
+ # end
304
+ # str # => "foo,0|bar,1|baz,2|"
305
+ # ary = CSV.parse(str, row_sep: row_sep)
306
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
307
+ #
308
+ # Using `--` (two hyphens):
309
+ # row_sep = '--'
310
+ # str = CSV.generate(row_sep: row_sep) do |csv|
311
+ # csv << [:foo, 0]
312
+ # csv << [:bar, 1]
313
+ # csv << [:baz, 2]
314
+ # end
315
+ # str # => "foo,0--bar,1--baz,2--"
316
+ # ary = CSV.parse(str, row_sep: row_sep)
317
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
318
+ #
319
+ # Using `''` (empty string):
320
+ # row_sep = ''
321
+ # str = CSV.generate(row_sep: row_sep) do |csv|
322
+ # csv << [:foo, 0]
323
+ # csv << [:bar, 1]
324
+ # csv << [:baz, 2]
325
+ # end
326
+ # str # => "foo,0bar,1baz,2"
327
+ # ary = CSV.parse(str, row_sep: row_sep)
328
+ # ary # => [["foo", "0bar", "1baz", "2"]]
329
+ #
330
+ # ---
331
+ #
332
+ # When `row_sep` is the Symbol `:auto` (the default), generating uses `"\n"` as
333
+ # the row separator:
334
+ # str = CSV.generate do |csv|
335
+ # csv << [:foo, 0]
336
+ # csv << [:bar, 1]
337
+ # csv << [:baz, 2]
338
+ # end
339
+ # str # => "foo,0\nbar,1\nbaz,2\n"
340
+ #
341
+ # Parsing, on the other hand, invokes auto-discovery of the row separator.
342
+ #
343
+ # Auto-discovery reads ahead in the data looking for the next `\r\n`, `\n`, or
344
+ # `\r` sequence. The sequence will be selected even if it occurs in a quoted
345
+ # field, assuming that you would have the same line endings there.
346
+ #
347
+ # Example:
348
+ # str = CSV.generate do |csv|
349
+ # csv << [:foo, 0]
350
+ # csv << [:bar, 1]
351
+ # csv << [:baz, 2]
352
+ # end
353
+ # str # => "foo,0\nbar,1\nbaz,2\n"
354
+ # ary = CSV.parse(str)
355
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
356
+ #
357
+ # The default `$INPUT_RECORD_SEPARATOR` (`$/`) is used if any of the following
358
+ # is true:
359
+ # * None of those sequences is found.
360
+ # * Data is `ARGF`, `STDIN`, `STDOUT`, or `STDERR`.
361
+ # * The stream is only available for output.
362
+ #
363
+ #
364
+ # Obviously, discovery takes a little time. Set manually if speed is important.
365
+ # Also note that IO objects should be opened in binary mode on Windows if this
366
+ # feature will be used as the line-ending translation can cause problems with
367
+ # resetting the document position to where it was before the read ahead.
368
+ #
369
+ # ---
370
+ #
371
+ # Raises an exception if the given value is not String-convertible:
372
+ # row_sep = BasicObject.new
373
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
374
+ # CSV.generate(ary, row_sep: row_sep)
375
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
376
+ # CSV.parse(str, row_sep: row_sep)
377
+ #
378
+ # ###### Option `col_sep`
379
+ #
380
+ # Specifies the String field separator to be used for both parsing and
381
+ # generating. The String will be transcoded into the data's Encoding before use.
382
+ #
383
+ # Default value:
384
+ # CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma)
385
+ #
386
+ # Using the default (comma):
387
+ # str = CSV.generate do |csv|
388
+ # csv << [:foo, 0]
389
+ # csv << [:bar, 1]
390
+ # csv << [:baz, 2]
391
+ # end
392
+ # str # => "foo,0\nbar,1\nbaz,2\n"
393
+ # ary = CSV.parse(str)
394
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
395
+ #
396
+ # Using `:` (colon):
397
+ # col_sep = ':'
398
+ # str = CSV.generate(col_sep: col_sep) do |csv|
399
+ # csv << [:foo, 0]
400
+ # csv << [:bar, 1]
401
+ # csv << [:baz, 2]
402
+ # end
403
+ # str # => "foo:0\nbar:1\nbaz:2\n"
404
+ # ary = CSV.parse(str, col_sep: col_sep)
405
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
406
+ #
407
+ # Using `::` (two colons):
408
+ # col_sep = '::'
409
+ # str = CSV.generate(col_sep: col_sep) do |csv|
410
+ # csv << [:foo, 0]
411
+ # csv << [:bar, 1]
412
+ # csv << [:baz, 2]
413
+ # end
414
+ # str # => "foo::0\nbar::1\nbaz::2\n"
415
+ # ary = CSV.parse(str, col_sep: col_sep)
416
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
417
+ #
418
+ # Using `''` (empty string):
419
+ # col_sep = ''
420
+ # str = CSV.generate(col_sep: col_sep) do |csv|
421
+ # csv << [:foo, 0]
422
+ # csv << [:bar, 1]
423
+ # csv << [:baz, 2]
424
+ # end
425
+ # str # => "foo0\nbar1\nbaz2\n"
426
+ #
427
+ # ---
428
+ #
429
+ # Raises an exception if parsing with the empty String:
430
+ # col_sep = ''
431
+ # # Raises ArgumentError (:col_sep must be 1 or more characters: "")
432
+ # CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep)
433
+ #
434
+ # Raises an exception if the given value is not String-convertible:
435
+ # col_sep = BasicObject.new
436
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
437
+ # CSV.generate(line, col_sep: col_sep)
438
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
439
+ # CSV.parse(str, col_sep: col_sep)
440
+ #
441
+ # ###### Option `quote_char`
442
+ #
443
+ # Specifies the character (String of length 1) used used to quote fields in both
444
+ # parsing and generating. This String will be transcoded into the data's
445
+ # Encoding before use.
446
+ #
447
+ # Default value:
448
+ # CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote)
449
+ #
450
+ # This is useful for an application that incorrectly uses `'` (single-quote) to
451
+ # quote fields, instead of the correct `"` (double-quote).
452
+ #
453
+ # Using the default (double quote):
454
+ # str = CSV.generate do |csv|
455
+ # csv << ['foo', 0]
456
+ # csv << ["'bar'", 1]
457
+ # csv << ['"baz"', 2]
458
+ # end
459
+ # str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n"
460
+ # ary = CSV.parse(str)
461
+ # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
462
+ #
463
+ # Using `'` (single-quote):
464
+ # quote_char = "'"
465
+ # str = CSV.generate(quote_char: quote_char) do |csv|
466
+ # csv << ['foo', 0]
467
+ # csv << ["'bar'", 1]
468
+ # csv << ['"baz"', 2]
63
469
  # end
470
+ # str # => "foo,0\n'''bar''',1\n\"baz\",2\n"
471
+ # ary = CSV.parse(str, quote_char: quote_char)
472
+ # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
473
+ #
474
+ # ---
475
+ #
476
+ # Raises an exception if the String length is greater than 1:
477
+ # # Raises ArgumentError (:quote_char has to be nil or a single character String)
478
+ # CSV.new('', quote_char: 'xx')
479
+ #
480
+ # Raises an exception if the value is not a String:
481
+ # # Raises ArgumentError (:quote_char has to be nil or a single character String)
482
+ # CSV.new('', quote_char: :foo)
483
+ #
484
+ # ###### Option `field_size_limit`
485
+ #
486
+ # Specifies the Integer field size limit.
487
+ #
488
+ # Default value:
489
+ # CSV::DEFAULT_OPTIONS.fetch(:field_size_limit) # => nil
490
+ #
491
+ # This is a maximum size CSV will read ahead looking for the closing quote for a
492
+ # field. (In truth, it reads to the first line ending beyond this size.) If a
493
+ # quote cannot be found within the limit CSV will raise a MalformedCSVError,
494
+ # assuming the data is faulty. You can use this limit to prevent what are
495
+ # effectively DoS attacks on the parser. However, this limit can cause a
496
+ # legitimate parse to fail; therefore the default value is `nil` (no limit).
497
+ #
498
+ # For the examples in this section:
499
+ # str = <<~EOT
500
+ # "a","b"
501
+ # "
502
+ # 2345
503
+ # ",""
504
+ # EOT
505
+ # str # => "\"a\",\"b\"\n\"\n2345\n\",\"\"\n"
506
+ #
507
+ # Using the default `nil`:
508
+ # ary = CSV.parse(str)
509
+ # ary # => [["a", "b"], ["\n2345\n", ""]]
510
+ #
511
+ # Using `50`:
512
+ # field_size_limit = 50
513
+ # ary = CSV.parse(str, field_size_limit: field_size_limit)
514
+ # ary # => [["a", "b"], ["\n2345\n", ""]]
515
+ #
516
+ # ---
517
+ #
518
+ # Raises an exception if a field is too long:
519
+ # big_str = "123456789\n" * 1024
520
+ # # Raises CSV::MalformedCSVError (Field size exceeded in line 1.)
521
+ # CSV.parse('valid,fields,"' + big_str + '"', field_size_limit: 2048)
522
+ #
523
+ # ###### Option `converters`
524
+ #
525
+ # Specifies converters to be used in parsing fields. See [Field
526
+ # Converters](#class-CSV-label-Field+Converters)
527
+ #
528
+ # Default value:
529
+ # CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil
530
+ #
531
+ # The value may be a field converter name (see [Stored
532
+ # Converters](#class-CSV-label-Stored+Converters)):
533
+ # str = '1,2,3'
534
+ # # Without a converter
535
+ # array = CSV.parse_line(str)
536
+ # array # => ["1", "2", "3"]
537
+ # # With built-in converter :integer
538
+ # array = CSV.parse_line(str, converters: :integer)
539
+ # array # => [1, 2, 3]
540
+ #
541
+ # The value may be a converter list (see [Converter
542
+ # Lists](#class-CSV-label-Converter+Lists)):
543
+ # str = '1,3.14159'
544
+ # # Without converters
545
+ # array = CSV.parse_line(str)
546
+ # array # => ["1", "3.14159"]
547
+ # # With built-in converters
548
+ # array = CSV.parse_line(str, converters: [:integer, :float])
549
+ # array # => [1, 3.14159]
550
+ #
551
+ # The value may be a Proc custom converter: (see [Custom Field
552
+ # Converters](#class-CSV-label-Custom+Field+Converters)):
553
+ # str = ' foo , bar , baz '
554
+ # # Without a converter
555
+ # array = CSV.parse_line(str)
556
+ # array # => [" foo ", " bar ", " baz "]
557
+ # # With a custom converter
558
+ # array = CSV.parse_line(str, converters: proc {|field| field.strip })
559
+ # array # => ["foo", "bar", "baz"]
560
+ #
561
+ # See also [Custom Field Converters](#class-CSV-label-Custom+Field+Converters)
562
+ #
563
+ # ---
564
+ #
565
+ # Raises an exception if the converter is not a converter name or a Proc:
566
+ # str = 'foo,0'
567
+ # # Raises NoMethodError (undefined method `arity' for nil:NilClass)
568
+ # CSV.parse(str, converters: :foo)
569
+ #
570
+ # ###### Option `unconverted_fields`
571
+ #
572
+ # Specifies the boolean that determines whether unconverted field values are to
573
+ # be available.
574
+ #
575
+ # Default value:
576
+ # CSV::DEFAULT_OPTIONS.fetch(:unconverted_fields) # => nil
577
+ #
578
+ # The unconverted field values are those found in the source data, prior to any
579
+ # conversions performed via option `converters`.
580
+ #
581
+ # When option `unconverted_fields` is `true`, each returned row (Array or
582
+ # CSV::Row) has an added method, `unconverted_fields`, that returns the
583
+ # unconverted field values:
584
+ # str = <<-EOT
585
+ # foo,0
586
+ # bar,1
587
+ # baz,2
588
+ # EOT
589
+ # # Without unconverted_fields
590
+ # csv = CSV.parse(str, converters: :integer)
591
+ # csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
592
+ # csv.first.respond_to?(:unconverted_fields) # => false
593
+ # # With unconverted_fields
594
+ # csv = CSV.parse(str, converters: :integer, unconverted_fields: true)
595
+ # csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
596
+ # csv.first.respond_to?(:unconverted_fields) # => true
597
+ # csv.first.unconverted_fields # => ["foo", "0"]
598
+ #
599
+ # ###### Option `headers`
600
+ #
601
+ # Specifies a boolean, Symbol, Array, or String to be used to define column
602
+ # headers.
603
+ #
604
+ # Default value:
605
+ # CSV::DEFAULT_OPTIONS.fetch(:headers) # => false
606
+ #
607
+ # ---
608
+ #
609
+ # Without `headers`:
610
+ # str = <<-EOT
611
+ # Name,Count
612
+ # foo,0
613
+ # bar,1
614
+ # bax,2
615
+ # EOT
616
+ # csv = CSV.new(str)
617
+ # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
618
+ # csv.headers # => nil
619
+ # csv.shift # => ["Name", "Count"]
620
+ #
621
+ # ---
622
+ #
623
+ # If set to `true` or the Symbol `:first_row`, the first row of the data is
624
+ # treated as a row of headers:
625
+ # str = <<-EOT
626
+ # Name,Count
627
+ # foo,0
628
+ # bar,1
629
+ # bax,2
630
+ # EOT
631
+ # csv = CSV.new(str, headers: true)
632
+ # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["Name", "Count"]>
633
+ # csv.headers # => ["Name", "Count"]
634
+ # csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
635
+ #
636
+ # ---
637
+ #
638
+ # If set to an Array, the Array elements are treated as headers:
639
+ # str = <<-EOT
640
+ # foo,0
641
+ # bar,1
642
+ # bax,2
643
+ # EOT
644
+ # csv = CSV.new(str, headers: ['Name', 'Count'])
645
+ # csv
646
+ # csv.headers # => ["Name", "Count"]
647
+ # csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
648
+ #
649
+ # ---
650
+ #
651
+ # If set to a String `str`, method `CSV::parse_line(str, options)` is called
652
+ # with the current `options`, and the returned Array is treated as headers:
653
+ # str = <<-EOT
654
+ # foo,0
655
+ # bar,1
656
+ # bax,2
657
+ # EOT
658
+ # csv = CSV.new(str, headers: 'Name,Count')
659
+ # csv
660
+ # csv.headers # => ["Name", "Count"]
661
+ # csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
662
+ #
663
+ # ###### Option `return_headers`
664
+ #
665
+ # Specifies the boolean that determines whether method #shift returns or ignores
666
+ # the header row.
667
+ #
668
+ # Default value:
669
+ # CSV::DEFAULT_OPTIONS.fetch(:return_headers) # => false
670
+ #
671
+ # Examples:
672
+ # str = <<-EOT
673
+ # Name,Count
674
+ # foo,0
675
+ # bar,1
676
+ # bax,2
677
+ # EOT
678
+ # # Without return_headers first row is str.
679
+ # csv = CSV.new(str, headers: true)
680
+ # csv.shift # => #<CSV::Row "Name":"foo" "Count":"0">
681
+ # # With return_headers first row is headers.
682
+ # csv = CSV.new(str, headers: true, return_headers: true)
683
+ # csv.shift # => #<CSV::Row "Name":"Name" "Count":"Count">
684
+ #
685
+ # ###### Option `header_converters`
686
+ #
687
+ # Specifies converters to be used in parsing headers. See [Header
688
+ # Converters](#class-CSV-label-Header+Converters)
689
+ #
690
+ # Default value:
691
+ # CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil
692
+ #
693
+ # Identical in functionality to option
694
+ # [converters](#class-CSV-label-Option+converters) except that:
695
+ # * The converters apply only to the header row.
696
+ # * The built-in header converters are `:downcase` and `:symbol`.
697
+ #
698
+ #
699
+ # This section assumes prior execution of:
700
+ # str = <<-EOT
701
+ # Name,Value
702
+ # foo,0
703
+ # bar,1
704
+ # baz,2
705
+ # EOT
706
+ # # With no header converter
707
+ # table = CSV.parse(str, headers: true)
708
+ # table.headers # => ["Name", "Value"]
709
+ #
710
+ # The value may be a header converter name (see [Stored
711
+ # Converters](#class-CSV-label-Stored+Converters)):
712
+ # table = CSV.parse(str, headers: true, header_converters: :downcase)
713
+ # table.headers # => ["name", "value"]
714
+ #
715
+ # The value may be a converter list (see [Converter
716
+ # Lists](#class-CSV-label-Converter+Lists)):
717
+ # header_converters = [:downcase, :symbol]
718
+ # table = CSV.parse(str, headers: true, header_converters: header_converters)
719
+ # table.headers # => [:name, :value]
720
+ #
721
+ # The value may be a Proc custom converter (see [Custom Header
722
+ # Converters](#class-CSV-label-Custom+Header+Converters)):
723
+ # upcase_converter = proc {|field| field.upcase }
724
+ # table = CSV.parse(str, headers: true, header_converters: upcase_converter)
725
+ # table.headers # => ["NAME", "VALUE"]
726
+ #
727
+ # See also [Custom Header Converters](#class-CSV-label-Custom+Header+Converters)
728
+ #
729
+ # ###### Option `skip_blanks`
730
+ #
731
+ # Specifies a boolean that determines whether blank lines in the input will be
732
+ # ignored; a line that contains a column separator is not considered to be
733
+ # blank.
734
+ #
735
+ # Default value:
736
+ # CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false
737
+ #
738
+ # See also option [skiplines](#class-CSV-label-Option+skip_lines).
739
+ #
740
+ # For examples in this section:
741
+ # str = <<-EOT
742
+ # foo,0
743
+ #
744
+ # bar,1
745
+ # baz,2
746
+ #
747
+ # ,
748
+ # EOT
749
+ #
750
+ # Using the default, `false`:
751
+ # ary = CSV.parse(str)
752
+ # ary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]]
753
+ #
754
+ # Using `true`:
755
+ # ary = CSV.parse(str, skip_blanks: true)
756
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
757
+ #
758
+ # Using a truthy value:
759
+ # ary = CSV.parse(str, skip_blanks: :foo)
760
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
761
+ #
762
+ # ###### Option `skip_lines`
763
+ #
764
+ # Specifies an object to use in identifying comment lines in the input that are
765
+ # to be ignored:
766
+ # * If a Regexp, ignores lines that match it.
767
+ # * If a String, converts it to a Regexp, ignores lines that match it.
768
+ # * If `nil`, no lines are considered to be comments.
769
+ #
770
+ #
771
+ # Default value:
772
+ # CSV::DEFAULT_OPTIONS.fetch(:skip_lines) # => nil
773
+ #
774
+ # For examples in this section:
775
+ # str = <<-EOT
776
+ # # Comment
777
+ # foo,0
778
+ # bar,1
779
+ # baz,2
780
+ # # Another comment
781
+ # EOT
782
+ # str # => "# Comment\nfoo,0\nbar,1\nbaz,2\n# Another comment\n"
783
+ #
784
+ # Using the default, `nil`:
785
+ # ary = CSV.parse(str)
786
+ # ary # => [["# Comment"], ["foo", "0"], ["bar", "1"], ["baz", "2"], ["# Another comment"]]
787
+ #
788
+ # Using a Regexp:
789
+ # ary = CSV.parse(str, skip_lines: /^#/)
790
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
791
+ #
792
+ # Using a String:
793
+ # ary = CSV.parse(str, skip_lines: '#')
794
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
795
+ #
796
+ # ---
797
+ #
798
+ # Raises an exception if given an object that is not a Regexp, a String, or
799
+ # `nil`:
800
+ # # Raises ArgumentError (:skip_lines has to respond to #match: 0)
801
+ # CSV.parse(str, skip_lines: 0)
802
+ #
803
+ # ###### Option `strip`
804
+ #
805
+ # Specifies the boolean value that determines whether whitespace is stripped
806
+ # from each input field.
807
+ #
808
+ # Default value:
809
+ # CSV::DEFAULT_OPTIONS.fetch(:strip) # => false
810
+ #
811
+ # With default value `false`:
812
+ # ary = CSV.parse_line(' a , b ')
813
+ # ary # => [" a ", " b "]
814
+ #
815
+ # With value `true`:
816
+ # ary = CSV.parse_line(' a , b ', strip: true)
817
+ # ary # => ["a", "b"]
818
+ #
819
+ # ###### Option `liberal_parsing`
820
+ #
821
+ # Specifies the boolean value that determines whether CSV will attempt to parse
822
+ # input not conformant with RFC 4180, such as double quotes in unquoted fields.
823
+ #
824
+ # Default value:
825
+ # CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false
826
+ #
827
+ # For examples in this section:
828
+ # str = 'is,this "three, or four",fields'
829
+ #
830
+ # Without `liberal_parsing`:
831
+ # # Raises CSV::MalformedCSVError (Illegal quoting in str 1.)
832
+ # CSV.parse_line(str)
833
+ #
834
+ # With `liberal_parsing`:
835
+ # ary = CSV.parse_line(str, liberal_parsing: true)
836
+ # ary # => ["is", "this \"three", " or four\"", "fields"]
837
+ #
838
+ # ###### Option `nil_value`
839
+ #
840
+ # Specifies the object that is to be substituted for each null (no-text) field.
841
+ #
842
+ # Default value:
843
+ # CSV::DEFAULT_OPTIONS.fetch(:nil_value) # => nil
844
+ #
845
+ # With the default, `nil`:
846
+ # CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"]
847
+ #
848
+ # With a different object:
849
+ # CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"]
850
+ #
851
+ # ###### Option `empty_value`
852
+ #
853
+ # Specifies the object that is to be substituted for each field that has an
854
+ # empty String.
855
+ #
856
+ # Default value:
857
+ # CSV::DEFAULT_OPTIONS.fetch(:empty_value) # => "" (empty string)
858
+ #
859
+ # With the default, `""`:
860
+ # CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"]
64
861
  #
65
- # ### Shortcuts
862
+ # With a different object:
863
+ # CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"]
66
864
  #
67
- # # Core extensions for converting one line
68
- # csv_string = ["CSV", "data"].to_csv # to CSV
69
- # csv_array = "CSV,String".parse_csv # from CSV
865
+ # #### Options for Generating
70
866
  #
71
- # # CSV() method
72
- # CSV { |csv_out| csv_out << %w{my data here} } # to $stdout
73
- # CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String
74
- # CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
75
- # CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin
867
+ # Options for generating, described in detail below, include:
868
+ # * `row_sep`: Specifies the row separator; used to delimit rows.
869
+ # * `col_sep`: Specifies the column separator; used to delimit fields.
870
+ # * `quote_char`: Specifies the quote character; used to quote fields.
871
+ # * `write_headers`: Specifies whether headers are to be written.
872
+ # * `force_quotes`: Specifies whether each output field is to be quoted.
873
+ # * `quote_empty`: Specifies whether each empty output field is to be quoted.
874
+ # * `write_converters`: Specifies the field converters to be used in writing.
875
+ # * `write_nil_value`: Specifies the object that is to be substituted for each
876
+ # `nil`-valued field.
877
+ # * `write_empty_value`: Specifies the object that is to be substituted for
878
+ # each empty field.
76
879
  #
77
- # ## Data Conversion
78
880
  #
79
- # ### CSV with headers
881
+ # ###### Option `row_sep`
882
+ #
883
+ # Specifies the row separator, a String or the Symbol `:auto` (see below), to be
884
+ # used for both parsing and generating.
885
+ #
886
+ # Default value:
887
+ # CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto
888
+ #
889
+ # ---
890
+ #
891
+ # When `row_sep` is a String, that String becomes the row separator. The String
892
+ # will be transcoded into the data's Encoding before use.
893
+ #
894
+ # Using `"\n"`:
895
+ # row_sep = "\n"
896
+ # str = CSV.generate(row_sep: row_sep) do |csv|
897
+ # csv << [:foo, 0]
898
+ # csv << [:bar, 1]
899
+ # csv << [:baz, 2]
900
+ # end
901
+ # str # => "foo,0\nbar,1\nbaz,2\n"
902
+ # ary = CSV.parse(str)
903
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
904
+ #
905
+ # Using `|` (pipe):
906
+ # row_sep = '|'
907
+ # str = CSV.generate(row_sep: row_sep) do |csv|
908
+ # csv << [:foo, 0]
909
+ # csv << [:bar, 1]
910
+ # csv << [:baz, 2]
911
+ # end
912
+ # str # => "foo,0|bar,1|baz,2|"
913
+ # ary = CSV.parse(str, row_sep: row_sep)
914
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
915
+ #
916
+ # Using `--` (two hyphens):
917
+ # row_sep = '--'
918
+ # str = CSV.generate(row_sep: row_sep) do |csv|
919
+ # csv << [:foo, 0]
920
+ # csv << [:bar, 1]
921
+ # csv << [:baz, 2]
922
+ # end
923
+ # str # => "foo,0--bar,1--baz,2--"
924
+ # ary = CSV.parse(str, row_sep: row_sep)
925
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
926
+ #
927
+ # Using `''` (empty string):
928
+ # row_sep = ''
929
+ # str = CSV.generate(row_sep: row_sep) do |csv|
930
+ # csv << [:foo, 0]
931
+ # csv << [:bar, 1]
932
+ # csv << [:baz, 2]
933
+ # end
934
+ # str # => "foo,0bar,1baz,2"
935
+ # ary = CSV.parse(str, row_sep: row_sep)
936
+ # ary # => [["foo", "0bar", "1baz", "2"]]
937
+ #
938
+ # ---
939
+ #
940
+ # When `row_sep` is the Symbol `:auto` (the default), generating uses `"\n"` as
941
+ # the row separator:
942
+ # str = CSV.generate do |csv|
943
+ # csv << [:foo, 0]
944
+ # csv << [:bar, 1]
945
+ # csv << [:baz, 2]
946
+ # end
947
+ # str # => "foo,0\nbar,1\nbaz,2\n"
948
+ #
949
+ # Parsing, on the other hand, invokes auto-discovery of the row separator.
950
+ #
951
+ # Auto-discovery reads ahead in the data looking for the next `\r\n`, `\n`, or
952
+ # `\r` sequence. The sequence will be selected even if it occurs in a quoted
953
+ # field, assuming that you would have the same line endings there.
954
+ #
955
+ # Example:
956
+ # str = CSV.generate do |csv|
957
+ # csv << [:foo, 0]
958
+ # csv << [:bar, 1]
959
+ # csv << [:baz, 2]
960
+ # end
961
+ # str # => "foo,0\nbar,1\nbaz,2\n"
962
+ # ary = CSV.parse(str)
963
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
964
+ #
965
+ # The default `$INPUT_RECORD_SEPARATOR` (`$/`) is used if any of the following
966
+ # is true:
967
+ # * None of those sequences is found.
968
+ # * Data is `ARGF`, `STDIN`, `STDOUT`, or `STDERR`.
969
+ # * The stream is only available for output.
970
+ #
971
+ #
972
+ # Obviously, discovery takes a little time. Set manually if speed is important.
973
+ # Also note that IO objects should be opened in binary mode on Windows if this
974
+ # feature will be used as the line-ending translation can cause problems with
975
+ # resetting the document position to where it was before the read ahead.
976
+ #
977
+ # ---
978
+ #
979
+ # Raises an exception if the given value is not String-convertible:
980
+ # row_sep = BasicObject.new
981
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
982
+ # CSV.generate(ary, row_sep: row_sep)
983
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
984
+ # CSV.parse(str, row_sep: row_sep)
985
+ #
986
+ # ###### Option `col_sep`
987
+ #
988
+ # Specifies the String field separator to be used for both parsing and
989
+ # generating. The String will be transcoded into the data's Encoding before use.
990
+ #
991
+ # Default value:
992
+ # CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma)
993
+ #
994
+ # Using the default (comma):
995
+ # str = CSV.generate do |csv|
996
+ # csv << [:foo, 0]
997
+ # csv << [:bar, 1]
998
+ # csv << [:baz, 2]
999
+ # end
1000
+ # str # => "foo,0\nbar,1\nbaz,2\n"
1001
+ # ary = CSV.parse(str)
1002
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1003
+ #
1004
+ # Using `:` (colon):
1005
+ # col_sep = ':'
1006
+ # str = CSV.generate(col_sep: col_sep) do |csv|
1007
+ # csv << [:foo, 0]
1008
+ # csv << [:bar, 1]
1009
+ # csv << [:baz, 2]
1010
+ # end
1011
+ # str # => "foo:0\nbar:1\nbaz:2\n"
1012
+ # ary = CSV.parse(str, col_sep: col_sep)
1013
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1014
+ #
1015
+ # Using `::` (two colons):
1016
+ # col_sep = '::'
1017
+ # str = CSV.generate(col_sep: col_sep) do |csv|
1018
+ # csv << [:foo, 0]
1019
+ # csv << [:bar, 1]
1020
+ # csv << [:baz, 2]
1021
+ # end
1022
+ # str # => "foo::0\nbar::1\nbaz::2\n"
1023
+ # ary = CSV.parse(str, col_sep: col_sep)
1024
+ # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1025
+ #
1026
+ # Using `''` (empty string):
1027
+ # col_sep = ''
1028
+ # str = CSV.generate(col_sep: col_sep) do |csv|
1029
+ # csv << [:foo, 0]
1030
+ # csv << [:bar, 1]
1031
+ # csv << [:baz, 2]
1032
+ # end
1033
+ # str # => "foo0\nbar1\nbaz2\n"
1034
+ #
1035
+ # ---
1036
+ #
1037
+ # Raises an exception if parsing with the empty String:
1038
+ # col_sep = ''
1039
+ # # Raises ArgumentError (:col_sep must be 1 or more characters: "")
1040
+ # CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep)
1041
+ #
1042
+ # Raises an exception if the given value is not String-convertible:
1043
+ # col_sep = BasicObject.new
1044
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
1045
+ # CSV.generate(line, col_sep: col_sep)
1046
+ # # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
1047
+ # CSV.parse(str, col_sep: col_sep)
1048
+ #
1049
+ # ###### Option `quote_char`
1050
+ #
1051
+ # Specifies the character (String of length 1) used used to quote fields in both
1052
+ # parsing and generating. This String will be transcoded into the data's
1053
+ # Encoding before use.
1054
+ #
1055
+ # Default value:
1056
+ # CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote)
1057
+ #
1058
+ # This is useful for an application that incorrectly uses `'` (single-quote) to
1059
+ # quote fields, instead of the correct `"` (double-quote).
1060
+ #
1061
+ # Using the default (double quote):
1062
+ # str = CSV.generate do |csv|
1063
+ # csv << ['foo', 0]
1064
+ # csv << ["'bar'", 1]
1065
+ # csv << ['"baz"', 2]
1066
+ # end
1067
+ # str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n"
1068
+ # ary = CSV.parse(str)
1069
+ # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
1070
+ #
1071
+ # Using `'` (single-quote):
1072
+ # quote_char = "'"
1073
+ # str = CSV.generate(quote_char: quote_char) do |csv|
1074
+ # csv << ['foo', 0]
1075
+ # csv << ["'bar'", 1]
1076
+ # csv << ['"baz"', 2]
1077
+ # end
1078
+ # str # => "foo,0\n'''bar''',1\n\"baz\",2\n"
1079
+ # ary = CSV.parse(str, quote_char: quote_char)
1080
+ # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
1081
+ #
1082
+ # ---
1083
+ #
1084
+ # Raises an exception if the String length is greater than 1:
1085
+ # # Raises ArgumentError (:quote_char has to be nil or a single character String)
1086
+ # CSV.new('', quote_char: 'xx')
1087
+ #
1088
+ # Raises an exception if the value is not a String:
1089
+ # # Raises ArgumentError (:quote_char has to be nil or a single character String)
1090
+ # CSV.new('', quote_char: :foo)
1091
+ #
1092
+ # ###### Option `write_headers`
1093
+ #
1094
+ # Specifies the boolean that determines whether a header row is included in the
1095
+ # output; ignored if there are no headers.
1096
+ #
1097
+ # Default value:
1098
+ # CSV::DEFAULT_OPTIONS.fetch(:write_headers) # => nil
1099
+ #
1100
+ # Without `write_headers`:
1101
+ # file_path = 't.csv'
1102
+ # CSV.open(file_path,'w',
1103
+ # :headers => ['Name','Value']
1104
+ # ) do |csv|
1105
+ # csv << ['foo', '0']
1106
+ # end
1107
+ # CSV.open(file_path) do |csv|
1108
+ # csv.shift
1109
+ # end # => ["foo", "0"]
1110
+ #
1111
+ # With `write_headers`":
1112
+ # CSV.open(file_path,'w',
1113
+ # :write_headers=> true,
1114
+ # :headers => ['Name','Value']
1115
+ # ) do |csv|
1116
+ # csv << ['foo', '0']
1117
+ # end
1118
+ # CSV.open(file_path) do |csv|
1119
+ # csv.shift
1120
+ # end # => ["Name", "Value"]
1121
+ #
1122
+ # ###### Option `force_quotes`
1123
+ #
1124
+ # Specifies the boolean that determines whether each output field is to be
1125
+ # double-quoted.
1126
+ #
1127
+ # Default value:
1128
+ # CSV::DEFAULT_OPTIONS.fetch(:force_quotes) # => false
1129
+ #
1130
+ # For examples in this section:
1131
+ # ary = ['foo', 0, nil]
1132
+ #
1133
+ # Using the default, `false`:
1134
+ # str = CSV.generate_line(ary)
1135
+ # str # => "foo,0,\n"
1136
+ #
1137
+ # Using `true`:
1138
+ # str = CSV.generate_line(ary, force_quotes: true)
1139
+ # str # => "\"foo\",\"0\",\"\"\n"
1140
+ #
1141
+ # ###### Option `quote_empty`
1142
+ #
1143
+ # Specifies the boolean that determines whether an empty value is to be
1144
+ # double-quoted.
1145
+ #
1146
+ # Default value:
1147
+ # CSV::DEFAULT_OPTIONS.fetch(:quote_empty) # => true
1148
+ #
1149
+ # With the default `true`:
1150
+ # CSV.generate_line(['"', ""]) # => "\"\"\"\",\"\"\n"
1151
+ #
1152
+ # With `false`:
1153
+ # CSV.generate_line(['"', ""], quote_empty: false) # => "\"\"\"\",\n"
1154
+ #
1155
+ # ###### Option `write_converters`
1156
+ #
1157
+ # Specifies converters to be used in generating fields. See [Write
1158
+ # Converters](#class-CSV-label-Write+Converters)
1159
+ #
1160
+ # Default value:
1161
+ # CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil
1162
+ #
1163
+ # With no write converter:
1164
+ # str = CSV.generate_line(["\na\n", "\tb\t", " c "])
1165
+ # str # => "\"\na\n\",\tb\t, c \n"
1166
+ #
1167
+ # With a write converter:
1168
+ # strip_converter = proc {|field| field.strip }
1169
+ # str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter)
1170
+ # str # => "a,b,c\n"
1171
+ #
1172
+ # With two write converters (called in order):
1173
+ # upcase_converter = proc {|field| field.upcase }
1174
+ # downcase_converter = proc {|field| field.downcase }
1175
+ # write_converters = [upcase_converter, downcase_converter]
1176
+ # str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters)
1177
+ # str # => "a,b,c\n"
1178
+ #
1179
+ # See also [Write Converters](#class-CSV-label-Write+Converters)
1180
+ #
1181
+ # ---
1182
+ #
1183
+ # Raises an exception if the converter returns a value that is neither `nil` nor
1184
+ # String-convertible:
1185
+ # bad_converter = proc {|field| BasicObject.new }
1186
+ # # Raises NoMethodError (undefined method `is_a?' for #<BasicObject:>)
1187
+ # CSV.generate_line(['a', 'b', 'c'], write_converters: bad_converter)#
1188
+ #
1189
+ # ###### Option `write_nil_value`
1190
+ #
1191
+ # Specifies the object that is to be substituted for each `nil`-valued field.
1192
+ #
1193
+ # Default value:
1194
+ # CSV::DEFAULT_OPTIONS.fetch(:write_nil_value) # => nil
1195
+ #
1196
+ # Without the option:
1197
+ # str = CSV.generate_line(['a', nil, 'c', nil])
1198
+ # str # => "a,,c,\n"
1199
+ #
1200
+ # With the option:
1201
+ # str = CSV.generate_line(['a', nil, 'c', nil], write_nil_value: "x")
1202
+ # str # => "a,x,c,x\n"
1203
+ #
1204
+ # ###### Option `write_empty_value`
1205
+ #
1206
+ # Specifies the object that is to be substituted for each field that has an
1207
+ # empty String.
1208
+ #
1209
+ # Default value:
1210
+ # CSV::DEFAULT_OPTIONS.fetch(:write_empty_value) # => ""
1211
+ #
1212
+ # Without the option:
1213
+ # str = CSV.generate_line(['a', '', 'c', ''])
1214
+ # str # => "a,\"\",c,\"\"\n"
1215
+ #
1216
+ # With the option:
1217
+ # str = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x")
1218
+ # str # => "a,x,c,x\n"
1219
+ #
1220
+ # ### CSV with Headers
80
1221
  #
81
1222
  # CSV allows to specify column names of CSV file, whether they are in data, or
82
1223
  # provided separately. If headers are specified, reading methods return an
83
1224
  # instance of CSV::Table, consisting of CSV::Row.
84
1225
  #
85
- # # Headers are part of data
86
- # data = CSV.parse(<<~ROWS, headers: true)
87
- # Name,Department,Salary
88
- # Bob,Engineering,1000
89
- # Jane,Sales,2000
90
- # John,Management,5000
91
- # ROWS
1226
+ # # Headers are part of data
1227
+ # data = CSV.parse(<<~ROWS, headers: true)
1228
+ # Name,Department,Salary
1229
+ # Bob,Engineering,1000
1230
+ # Jane,Sales,2000
1231
+ # John,Management,5000
1232
+ # ROWS
1233
+ #
1234
+ # data.class #=> CSV::Table
1235
+ # data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000">
1236
+ # data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
1237
+ #
1238
+ # # Headers provided by developer
1239
+ # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
1240
+ # data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
1241
+ #
1242
+ # ### Converters
1243
+ #
1244
+ # By default, each value (field or header) parsed by CSV is formed into a
1245
+ # String. You can use a *field* *converter* or *header* *converter* to
1246
+ # intercept and modify the parsed values:
1247
+ # * See [Field Converters](#class-CSV-label-Field+Converters).
1248
+ # * See [Header Converters](#class-CSV-label-Header+Converters).
1249
+ #
1250
+ #
1251
+ # Also by default, each value to be written during generation is written
1252
+ # 'as-is'. You can use a *write* *converter* to modify values before writing.
1253
+ # * See [Write Converters](#class-CSV-label-Write+Converters).
1254
+ #
1255
+ #
1256
+ # #### Specifying Converters
1257
+ #
1258
+ # You can specify converters for parsing or generating in the `options` argument
1259
+ # to various CSV methods:
1260
+ # * Option `converters` for converting parsed field values.
1261
+ # * Option `header_converters` for converting parsed header values.
1262
+ # * Option `write_converters` for converting values to be written (generated).
1263
+ #
1264
+ #
1265
+ # There are three forms for specifying converters:
1266
+ # * A converter proc: executable code to be used for conversion.
1267
+ # * A converter name: the name of a stored converter.
1268
+ # * A converter list: an array of converter procs, converter names, and
1269
+ # converter lists.
1270
+ #
1271
+ #
1272
+ # ##### Converter Procs
1273
+ #
1274
+ # This converter proc, `strip_converter`, accepts a value `field` and returns
1275
+ # `field.strip`:
1276
+ # strip_converter = proc {|field| field.strip }
1277
+ #
1278
+ # In this call to `CSV.parse`, the keyword argument `converters:
1279
+ # string_converter` specifies that:
1280
+ # * Proc `string_converter` is to be called for each parsed field.
1281
+ # * The converter's return value is to replace the `field` value.
1282
+ #
1283
+ # Example:
1284
+ # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1285
+ # array = CSV.parse(string, converters: strip_converter)
1286
+ # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1287
+ #
1288
+ # A converter proc can receive a second argument, `field_info`, that contains
1289
+ # details about the field. This modified `strip_converter` displays its
1290
+ # arguments:
1291
+ # strip_converter = proc do |field, field_info|
1292
+ # p [field, field_info]
1293
+ # field.strip
1294
+ # end
1295
+ # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1296
+ # array = CSV.parse(string, converters: strip_converter)
1297
+ # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1298
+ #
1299
+ # Output:
1300
+ # [" foo ", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
1301
+ # [" 0 ", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
1302
+ # [" bar ", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
1303
+ # [" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
1304
+ # [" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
1305
+ # [" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
1306
+ #
1307
+ # Each CSV::FieldInfo object shows:
1308
+ # * The 0-based field index.
1309
+ # * The 1-based line index.
1310
+ # * The field header, if any.
1311
+ #
1312
+ #
1313
+ # ##### Stored Converters
1314
+ #
1315
+ # A converter may be given a name and stored in a structure where the parsing
1316
+ # methods can find it by name.
1317
+ #
1318
+ # The storage structure for field converters is the Hash CSV::Converters. It has
1319
+ # several built-in converter procs:
1320
+ # * `:integer`: converts each String-embedded integer into a true Integer.
1321
+ # * `:float`: converts each String-embedded float into a true Float.
1322
+ # * `:date`: converts each String-embedded date into a true Date.
1323
+ # * `:date_time`: converts each String-embedded date-time into a true DateTime
1324
+ #
1325
+ # . This example creates a converter proc, then stores it:
1326
+ # strip_converter = proc {|field| field.strip }
1327
+ # CSV::Converters[:strip] = strip_converter
1328
+ #
1329
+ # Then the parsing method call can refer to the converter by its name, `:strip`:
1330
+ # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1331
+ # array = CSV.parse(string, converters: :strip)
1332
+ # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1333
+ #
1334
+ # The storage structure for header converters is the Hash CSV::HeaderConverters,
1335
+ # which works in the same way. It also has built-in converter procs:
1336
+ # * `:downcase`: Downcases each header.
1337
+ # * `:symbol`: Converts each header to a Symbol.
1338
+ #
1339
+ #
1340
+ # There is no such storage structure for write headers.
1341
+ #
1342
+ # In order for the parsing methods to access stored converters in
1343
+ # non-main-Ractors, the storage structure must be made shareable first.
1344
+ # Therefore, `Ractor.make_shareable(CSV::Converters)` and
1345
+ # `Ractor.make_shareable(CSV::HeaderConverters)` must be called before the
1346
+ # creation of Ractors that use the converters stored in these structures. (Since
1347
+ # making the storage structures shareable involves freezing them, any custom
1348
+ # converters that are to be used must be added first.)
1349
+ #
1350
+ # ##### Converter Lists
1351
+ #
1352
+ # A *converter* *list* is an Array that may include any assortment of:
1353
+ # * Converter procs.
1354
+ # * Names of stored converters.
1355
+ # * Nested converter lists.
1356
+ #
1357
+ #
1358
+ # Examples:
1359
+ # numeric_converters = [:integer, :float]
1360
+ # date_converters = [:date, :date_time]
1361
+ # [numeric_converters, strip_converter]
1362
+ # [strip_converter, date_converters, :float]
1363
+ #
1364
+ # Like a converter proc, a converter list may be named and stored in either
1365
+ # CSV::Converters or CSV::HeaderConverters:
1366
+ # CSV::Converters[:custom] = [strip_converter, date_converters, :float]
1367
+ # CSV::HeaderConverters[:custom] = [:downcase, :symbol]
1368
+ #
1369
+ # There are two built-in converter lists:
1370
+ # CSV::Converters[:numeric] # => [:integer, :float]
1371
+ # CSV::Converters[:all] # => [:date_time, :numeric]
1372
+ #
1373
+ # #### Field Converters
1374
+ #
1375
+ # With no conversion, all parsed fields in all rows become Strings:
1376
+ # string = "foo,0\nbar,1\nbaz,2\n"
1377
+ # ary = CSV.parse(string)
1378
+ # ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1379
+ #
1380
+ # When you specify a field converter, each parsed field is passed to the
1381
+ # converter; its return value becomes the stored value for the field. A
1382
+ # converter might, for example, convert an integer embedded in a String into a
1383
+ # true Integer. (In fact, that's what built-in field converter `:integer` does.)
1384
+ #
1385
+ # There are three ways to use field converters.
1386
+ #
1387
+ # * Using option [converters](#class-CSV-label-Option+converters) with a
1388
+ # parsing method:
1389
+ # ary = CSV.parse(string, converters: :integer)
1390
+ # ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]]
1391
+ #
1392
+ # * Using option [converters](#class-CSV-label-Option+converters) with a new
1393
+ # CSV instance:
1394
+ # csv = CSV.new(string, converters: :integer)
1395
+ # # Field converters in effect:
1396
+ # csv.converters # => [:integer]
1397
+ # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
1398
+ #
1399
+ # * Using method #convert to add a field converter to a CSV instance:
1400
+ # csv = CSV.new(string)
1401
+ # # Add a converter.
1402
+ # csv.convert(:integer)
1403
+ # csv.converters # => [:integer]
1404
+ # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
1405
+ #
1406
+ #
1407
+ # Installing a field converter does not affect already-read rows:
1408
+ # csv = CSV.new(string)
1409
+ # csv.shift # => ["foo", "0"]
1410
+ # # Add a converter.
1411
+ # csv.convert(:integer)
1412
+ # csv.converters # => [:integer]
1413
+ # csv.read # => [["bar", 1], ["baz", 2]]
1414
+ #
1415
+ # There are additional built-in converters, and custom converters are also
1416
+ # supported.
1417
+ #
1418
+ # ##### Built-In Field Converters
1419
+ #
1420
+ # The built-in field converters are in Hash CSV::Converters:
1421
+ # * Each key is a field converter name.
1422
+ # * Each value is one of:
1423
+ # * A Proc field converter.
1424
+ # * An Array of field converter names.
1425
+ #
1426
+ #
1427
+ #
1428
+ # Display:
1429
+ # CSV::Converters.each_pair do |name, value|
1430
+ # if value.kind_of?(Proc)
1431
+ # p [name, value.class]
1432
+ # else
1433
+ # p [name, value]
1434
+ # end
1435
+ # end
1436
+ #
1437
+ # Output:
1438
+ # [:integer, Proc]
1439
+ # [:float, Proc]
1440
+ # [:numeric, [:integer, :float]]
1441
+ # [:date, Proc]
1442
+ # [:date_time, Proc]
1443
+ # [:all, [:date_time, :numeric]]
1444
+ #
1445
+ # Each of these converters transcodes values to UTF-8 before attempting
1446
+ # conversion. If a value cannot be transcoded to UTF-8 the conversion will fail
1447
+ # and the value will remain unconverted.
1448
+ #
1449
+ # Converter `:integer` converts each field that Integer() accepts:
1450
+ # data = '0,1,2,x'
1451
+ # # Without the converter
1452
+ # csv = CSV.parse_line(data)
1453
+ # csv # => ["0", "1", "2", "x"]
1454
+ # # With the converter
1455
+ # csv = CSV.parse_line(data, converters: :integer)
1456
+ # csv # => [0, 1, 2, "x"]
1457
+ #
1458
+ # Converter `:float` converts each field that Float() accepts:
1459
+ # data = '1.0,3.14159,x'
1460
+ # # Without the converter
1461
+ # csv = CSV.parse_line(data)
1462
+ # csv # => ["1.0", "3.14159", "x"]
1463
+ # # With the converter
1464
+ # csv = CSV.parse_line(data, converters: :float)
1465
+ # csv # => [1.0, 3.14159, "x"]
1466
+ #
1467
+ # Converter `:numeric` converts with both `:integer` and `:float`..
1468
+ #
1469
+ # Converter `:date` converts each field that Date::parse accepts:
1470
+ # data = '2001-02-03,x'
1471
+ # # Without the converter
1472
+ # csv = CSV.parse_line(data)
1473
+ # csv # => ["2001-02-03", "x"]
1474
+ # # With the converter
1475
+ # csv = CSV.parse_line(data, converters: :date)
1476
+ # csv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"]
1477
+ #
1478
+ # Converter `:date_time` converts each field that DateTime::parse accepts:
1479
+ # data = '2020-05-07T14:59:00-05:00,x'
1480
+ # # Without the converter
1481
+ # csv = CSV.parse_line(data)
1482
+ # csv # => ["2020-05-07T14:59:00-05:00", "x"]
1483
+ # # With the converter
1484
+ # csv = CSV.parse_line(data, converters: :date_time)
1485
+ # csv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"]
1486
+ #
1487
+ # Converter `:numeric` converts with both `:date_time` and `:numeric`..
1488
+ #
1489
+ # As seen above, method #convert adds converters to a CSV instance, and method
1490
+ # #converters returns an Array of the converters in effect:
1491
+ # csv = CSV.new('0,1,2')
1492
+ # csv.converters # => []
1493
+ # csv.convert(:integer)
1494
+ # csv.converters # => [:integer]
1495
+ # csv.convert(:date)
1496
+ # csv.converters # => [:integer, :date]
1497
+ #
1498
+ # ##### Custom Field Converters
1499
+ #
1500
+ # You can define a custom field converter:
1501
+ # strip_converter = proc {|field| field.strip }
1502
+ # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1503
+ # array = CSV.parse(string, converters: strip_converter)
1504
+ # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1505
+ #
1506
+ # You can register the converter in Converters Hash, which allows you to refer
1507
+ # to it by name:
1508
+ # CSV::Converters[:strip] = strip_converter
1509
+ # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1510
+ # array = CSV.parse(string, converters: :strip)
1511
+ # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1512
+ #
1513
+ # #### Header Converters
1514
+ #
1515
+ # Header converters operate only on headers (and not on other rows).
1516
+ #
1517
+ # There are three ways to use header converters; these examples use built-in
1518
+ # header converter `:dowhcase`, which downcases each parsed header.
1519
+ #
1520
+ # * Option `header_converters` with a singleton parsing method:
1521
+ # string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
1522
+ # tbl = CSV.parse(string, headers: true, header_converters: :downcase)
1523
+ # tbl.class # => CSV::Table
1524
+ # tbl.headers # => ["name", "count"]
1525
+ #
1526
+ # * Option `header_converters` with a new CSV instance:
1527
+ # csv = CSV.new(string, header_converters: :downcase)
1528
+ # # Header converters in effect:
1529
+ # csv.header_converters # => [:downcase]
1530
+ # tbl = CSV.parse(string, headers: true)
1531
+ # tbl.headers # => ["Name", "Count"]
1532
+ #
1533
+ # * Method #header_convert adds a header converter to a CSV instance:
1534
+ # csv = CSV.new(string)
1535
+ # # Add a header converter.
1536
+ # csv.header_convert(:downcase)
1537
+ # csv.header_converters # => [:downcase]
1538
+ # tbl = CSV.parse(string, headers: true)
1539
+ # tbl.headers # => ["Name", "Count"]
1540
+ #
1541
+ #
1542
+ # ##### Built-In Header Converters
1543
+ #
1544
+ # The built-in header converters are in Hash CSV::HeaderConverters. The keys
1545
+ # there are the names of the converters:
1546
+ # CSV::HeaderConverters.keys # => [:downcase, :symbol]
1547
+ #
1548
+ # Converter `:downcase` converts each header by downcasing it:
1549
+ # string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
1550
+ # tbl = CSV.parse(string, headers: true, header_converters: :downcase)
1551
+ # tbl.class # => CSV::Table
1552
+ # tbl.headers # => ["name", "count"]
1553
+ #
1554
+ # Converter `:symbol` converts each header by making it into a Symbol:
1555
+ # string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
1556
+ # tbl = CSV.parse(string, headers: true, header_converters: :symbol)
1557
+ # tbl.headers # => [:name, :count]
1558
+ #
1559
+ # Details:
1560
+ # * Strips leading and trailing whitespace.
1561
+ # * Downcases the header.
1562
+ # * Replaces embedded spaces with underscores.
1563
+ # * Removes non-word characters.
1564
+ # * Makes the string into a Symbol.
1565
+ #
92
1566
  #
93
- # data.class #=> CSV::Table
94
- # data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000">
95
- # data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
1567
+ # ##### Custom Header Converters
96
1568
  #
97
- # # Headers provided by developer
98
- # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
99
- # data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
1569
+ # You can define a custom header converter:
1570
+ # upcase_converter = proc {|header| header.upcase }
1571
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
1572
+ # table = CSV.parse(string, headers: true, header_converters: upcase_converter)
1573
+ # table # => #<CSV::Table mode:col_or_row row_count:4>
1574
+ # table.headers # => ["NAME", "VALUE"]
100
1575
  #
101
- # ### Typed data reading
1576
+ # You can register the converter in HeaderConverters Hash, which allows you to
1577
+ # refer to it by name:
1578
+ # CSV::HeaderConverters[:upcase] = upcase_converter
1579
+ # table = CSV.parse(string, headers: true, header_converters: :upcase)
1580
+ # table # => #<CSV::Table mode:col_or_row row_count:4>
1581
+ # table.headers # => ["NAME", "VALUE"]
102
1582
  #
103
- # CSV allows to provide a set of data *converters* e.g. transformations to try
104
- # on input data. Converter could be a symbol from CSV::Converters constant's
105
- # keys, or lambda.
1583
+ # ##### Write Converters
106
1584
  #
107
- # # Without any converters:
108
- # CSV.parse('Bob,2018-03-01,100')
109
- # #=> [["Bob", "2018-03-01", "100"]]
1585
+ # When you specify a write converter for generating CSV, each field to be
1586
+ # written is passed to the converter; its return value becomes the new value for
1587
+ # the field. A converter might, for example, strip whitespace from a field.
110
1588
  #
111
- # # With built-in converters:
112
- # CSV.parse('Bob,2018-03-01,100', converters: %i[numeric date])
113
- # #=> [["Bob", #<Date: 2018-03-01>, 100]]
1589
+ # Using no write converter (all fields unmodified):
1590
+ # output_string = CSV.generate do |csv|
1591
+ # csv << [' foo ', 0]
1592
+ # csv << [' bar ', 1]
1593
+ # csv << [' baz ', 2]
1594
+ # end
1595
+ # output_string # => " foo ,0\n bar ,1\n baz ,2\n"
114
1596
  #
115
- # # With custom converters:
116
- # CSV.parse('Bob,2018-03-01,100', converters: [->(v) { Time.parse(v) rescue v }])
117
- # #=> [["Bob", 2018-03-01 00:00:00 +0200, "100"]]
1597
+ # Using option `write_converters` with two custom write converters:
1598
+ # strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
1599
+ # upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field }
1600
+ # write_converters = [strip_converter, upcase_converter]
1601
+ # output_string = CSV.generate(write_converters: write_converters) do |csv|
1602
+ # csv << [' foo ', 0]
1603
+ # csv << [' bar ', 1]
1604
+ # csv << [' baz ', 2]
1605
+ # end
1606
+ # output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
118
1607
  #
119
- # ## CSV and Character Encodings (M17n or Multilingualization)
1608
+ # ### Character Encodings (M17n or Multilingualization)
120
1609
  #
121
1610
  # This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
122
1611
  # or String object being read from or written to. Your data is never transcoded
@@ -162,287 +1651,605 @@ class CSV < Object
162
1651
  include Enumerable[untyped]
163
1652
  extend Forwardable
164
1653
 
165
- # This method is intended as the primary interface for reading CSV files. You
166
- # pass a `path` and any `options` you wish to set for the read. Each row of file
167
- # will be passed to the provided `block` in turn.
1654
+ # <!--
1655
+ # rdoc-file=lib/csv.rb
1656
+ # - foreach(path, mode='r', **options) {|row| ... )
1657
+ # - foreach(io, mode='r', **options {|row| ... )
1658
+ # - foreach(path, mode='r', headers: ..., **options) {|row| ... )
1659
+ # - foreach(io, mode='r', headers: ..., **options {|row| ... )
1660
+ # - foreach(path, mode='r', **options) -> new_enumerator
1661
+ # - foreach(io, mode='r', **options -> new_enumerator
1662
+ # -->
1663
+ # Calls the block with each row read from source `path` or `io`.
1664
+ #
1665
+ # * Argument `path`, if given, must be the path to a file.
1666
+ # * Argument `io` should be an IO object that is:
1667
+ # * Open for reading; on return, the IO object will be closed.
1668
+ # * Positioned at the beginning. To position at the end, for appending,
1669
+ # use method CSV.generate. For any other positioning, pass a preset
1670
+ # StringIO object instead.
1671
+ #
1672
+ # * Argument `mode`, if given, must be a File mode See [Open
1673
+ # Mode](IO.html#method-c-new-label-Open+Mode).
1674
+ # * Arguments `**options` must be keyword options. See [Options for
1675
+ # Parsing](#class-CSV-label-Options+for+Parsing).
1676
+ # * This method optionally accepts an additional `:encoding` option that you
1677
+ # can use to specify the Encoding of the data read from `path` or `io`. You
1678
+ # must provide this unless your data is in the encoding given by
1679
+ # `Encoding::default_external`. Parsing will use this to determine how to
1680
+ # parse the data. You may provide a second Encoding to have the data
1681
+ # transcoded as it is read. For example,
1682
+ # encoding: 'UTF-32BE:UTF-8'
1683
+ #
1684
+ # would read `UTF-32BE` data from the file but transcode it to `UTF-8`
1685
+ # before parsing.
1686
+ #
1687
+ #
1688
+ # ###### Without Option `headers`
1689
+ #
1690
+ # Without option `headers`, returns each row as an Array object.
1691
+ #
1692
+ # These examples assume prior execution of:
1693
+ # string = "foo,0\nbar,1\nbaz,2\n"
1694
+ # path = 't.csv'
1695
+ # File.write(path, string)
1696
+ #
1697
+ # Read rows from a file at `path`:
1698
+ # CSV.foreach(path) {|row| p row }
1699
+ #
1700
+ # Output:
1701
+ # ["foo", "0"]
1702
+ # ["bar", "1"]
1703
+ # ["baz", "2"]
1704
+ #
1705
+ # Read rows from an IO object:
1706
+ # File.open(path) do |file|
1707
+ # CSV.foreach(file) {|row| p row }
1708
+ # end
1709
+ #
1710
+ # Output:
1711
+ # ["foo", "0"]
1712
+ # ["bar", "1"]
1713
+ # ["baz", "2"]
1714
+ #
1715
+ # Returns a new Enumerator if no block given:
1716
+ # CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
1717
+ # CSV.foreach(File.open(path)) # => #<Enumerator: CSV:foreach(#<File:t.csv>, "r")>
1718
+ #
1719
+ # Issues a warning if an encoding is unsupported:
1720
+ # CSV.foreach(File.open(path), encoding: 'foo:bar') {|row| }
1721
+ #
1722
+ # Output:
1723
+ # warning: Unsupported encoding foo ignored
1724
+ # warning: Unsupported encoding bar ignored
1725
+ #
1726
+ # ###### With Option `headers`
1727
+ #
1728
+ # With {option `headers`[}](#class-CSV-label-Option+headers), returns each row
1729
+ # as a CSV::Row object.
1730
+ #
1731
+ # These examples assume prior execution of:
1732
+ # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
1733
+ # path = 't.csv'
1734
+ # File.write(path, string)
1735
+ #
1736
+ # Read rows from a file at `path`:
1737
+ # CSV.foreach(path, headers: true) {|row| p row }
1738
+ #
1739
+ # Output:
1740
+ # #<CSV::Row "Name":"foo" "Count":"0">
1741
+ # #<CSV::Row "Name":"bar" "Count":"1">
1742
+ # #<CSV::Row "Name":"baz" "Count":"2">
1743
+ #
1744
+ # Read rows from an IO object:
1745
+ # File.open(path) do |file|
1746
+ # CSV.foreach(file, headers: true) {|row| p row }
1747
+ # end
1748
+ #
1749
+ # Output:
1750
+ # #<CSV::Row "Name":"foo" "Count":"0">
1751
+ # #<CSV::Row "Name":"bar" "Count":"1">
1752
+ # #<CSV::Row "Name":"baz" "Count":"2">
1753
+ #
1754
+ # ---
1755
+ #
1756
+ # Raises an exception if `path` is a String, but not the path to a readable
1757
+ # file:
1758
+ # # Raises Errno::ENOENT (No such file or directory @ rb_sysopen - nosuch.csv):
1759
+ # CSV.foreach('nosuch.csv') {|row| }
168
1760
  #
169
- # The `options` parameter can be anything CSV::new() understands. This method
170
- # also understands an additional `:encoding` parameter that you can use to
171
- # specify the Encoding of the data in the file to be read. You must provide this
172
- # unless your data is in Encoding::default_external(). CSV will use this to
173
- # determine how to parse the data. You may provide a second Encoding to have the
174
- # data transcoded as it is read. For example, `encoding: "UTF-32BE:UTF-8"` would
175
- # read UTF-32BE data from the file but transcode it to UTF-8 before CSV parses
176
- # it.
1761
+ # Raises an exception if `io` is an IO object, but not open for reading:
1762
+ # io = File.open(path, 'w') {|row| }
1763
+ # # Raises TypeError (no implicit conversion of nil into String):
1764
+ # CSV.foreach(io) {|row| }
1765
+ #
1766
+ # Raises an exception if `mode` is invalid:
1767
+ # # Raises ArgumentError (invalid access mode nosuch):
1768
+ # CSV.foreach(path, 'nosuch') {|row| }
177
1769
  #
178
1770
  def self.foreach: [U] (String | IO | StringIO path, ?::Hash[Symbol, U] options) { (::Array[String?] arg0) -> void } -> void
179
1771
 
180
- # This constructor will wrap either a String or IO object passed in `data` for
181
- # reading and/or writing. In addition to the CSV instance methods, several IO
182
- # methods are delegated. (See CSV::open() for a complete list.) If you pass a
183
- # String for `data`, you can later retrieve it (after writing to it, for
184
- # example) with CSV.string().
185
- #
186
- # Note that a wrapped String will be positioned at the beginning (for reading).
187
- # If you want it at the end (for writing), use CSV::generate(). If you want any
188
- # other positioning, pass a preset StringIO object instead.
189
- #
190
- # You may set any reading and/or writing preferences in the `options` Hash.
191
- # Available options are:
192
- #
193
- # **`:col_sep`**
194
- # : The String placed between each field. This String will be transcoded into
195
- # the data's Encoding before parsing.
196
- # **`:row_sep`**
197
- # : The String appended to the end of each row. This can be set to the special
198
- # `:auto` setting, which requests that CSV automatically discover this from
199
- # the data. Auto-discovery reads ahead in the data looking for the next
200
- # `"\r\n"`, `"\n"`, or `"\r"` sequence. A sequence will be selected even if
201
- # it occurs in a quoted field, assuming that you would have the same line
202
- # endings there. If none of those sequences is found, `data` is `ARGF`,
203
- # `STDIN`, `STDOUT`, or `STDERR`, or the stream is only available for
204
- # output, the default `$INPUT_RECORD_SEPARATOR` (`$/`) is used. Obviously,
205
- # discovery takes a little time. Set manually if speed is important. Also
206
- # note that IO objects should be opened in binary mode on Windows if this
207
- # feature will be used as the line-ending translation can cause problems
208
- # with resetting the document position to where it was before the read
209
- # ahead. This String will be transcoded into the data's Encoding before
210
- # parsing.
211
- # **`:quote_char`**
212
- # : The character used to quote fields. This has to be a single character
213
- # String. This is useful for application that incorrectly use `'` as the
214
- # quote character instead of the correct `"`. CSV will always consider a
215
- # double sequence of this character to be an escaped quote. This String will
216
- # be transcoded into the data's Encoding before parsing.
217
- # **`:field_size_limit`**
218
- # : This is a maximum size CSV will read ahead looking for the closing quote
219
- # for a field. (In truth, it reads to the first line ending beyond this
220
- # size.) If a quote cannot be found within the limit CSV will raise a
221
- # MalformedCSVError, assuming the data is faulty. You can use this limit to
222
- # prevent what are effectively DoS attacks on the parser. However, this
223
- # limit can cause a legitimate parse to fail and thus is set to `nil`, or
224
- # off, by default.
225
- # **`:converters`**
226
- # : An Array of names from the Converters Hash and/or lambdas that handle
227
- # custom conversion. A single converter doesn't have to be in an Array. All
228
- # built-in converters try to transcode fields to UTF-8 before converting.
229
- # The conversion will fail if the data cannot be transcoded, leaving the
230
- # field unchanged.
231
- # **`:unconverted_fields`**
232
- # : If set to `true`, an unconverted_fields() method will be added to all
233
- # returned rows (Array or CSV::Row) that will return the fields as they were
234
- # before conversion. Note that `:headers` supplied by Array or String were
235
- # not fields of the document and thus will have an empty Array attached.
236
- # **`:headers`**
237
- # : If set to `:first_row` or `true`, the initial row of the CSV file will be
238
- # treated as a row of headers. If set to an Array, the contents will be used
239
- # as the headers. If set to a String, the String is run through a call of
240
- # CSV::parse_line() with the same `:col_sep`, `:row_sep`, and `:quote_char`
241
- # as this instance to produce an Array of headers. This setting causes
242
- # CSV#shift() to return rows as CSV::Row objects instead of Arrays and
243
- # CSV#read() to return CSV::Table objects instead of an Array of Arrays.
244
- # **`:return_headers`**
245
- # : When `false`, header rows are silently swallowed. If set to `true`, header
246
- # rows are returned in a CSV::Row object with identical headers and fields
247
- # (save that the fields do not go through the converters).
248
- # **`:write_headers`**
249
- # : When `true` and `:headers` is set, a header row will be added to the
250
- # output.
251
- # **`:header_converters`**
252
- # : Identical in functionality to `:converters` save that the conversions are
253
- # only made to header rows. All built-in converters try to transcode headers
254
- # to UTF-8 before converting. The conversion will fail if the data cannot be
255
- # transcoded, leaving the header unchanged.
256
- # **`:skip_blanks`**
257
- # : When setting a `true` value, CSV will skip over any empty rows. Note that
258
- # this setting will not skip rows that contain column separators, even if
259
- # the rows contain no actual data. If you want to skip rows that contain
260
- # separators but no content, consider using `:skip_lines`, or inspecting
261
- # fields.compact.empty? on each row.
262
- # **`:force_quotes`**
263
- # : When setting a `true` value, CSV will quote all CSV fields it creates.
264
- # **`:skip_lines`**
265
- # : When setting an object responding to `match`, every line matching it is
266
- # considered a comment and ignored during parsing. When set to a String, it
267
- # is first converted to a Regexp. When set to `nil` no line is considered a
268
- # comment. If the passed object does not respond to `match`, `ArgumentError`
269
- # is thrown.
270
- # **`:liberal_parsing`**
271
- # : When setting a `true` value, CSV will attempt to parse input not
272
- # conformant with RFC 4180, such as double quotes in unquoted fields.
273
- # **`:nil_value`**
274
- # : When set an object, any values of an empty field is replaced by the set
275
- # object, not nil.
276
- # **`:empty_value`**
277
- # : When setting an object, any values of a blank string field is replaced by
278
- # the set object.
279
- # **`:quote_empty`**
280
- # : When setting a `true` value, CSV will quote empty values with double
281
- # quotes. When `false`, CSV will emit an empty string for an empty field
282
- # value.
283
- # **`:write_converters`**
284
- # : Converts values on each line with the specified `Proc` object(s), which
285
- # receive a `String` value and return a `String` or `nil` value. When an
286
- # array is specified, each converter will be applied in order.
287
- # **`:write_nil_value`**
288
- # : When a `String` value, `nil` value(s) on each line will be replaced with
289
- # the specified value.
290
- # **`:write_empty_value`**
291
- # : When a `String` or `nil` value, empty value(s) on each line will be
292
- # replaced with the specified value.
293
- # **`:strip`**
294
- # : When setting a `true` value, CSV will strip "t\r\n\f\v" around the values.
295
- # If you specify a string instead of `true`, CSV will strip string. The
296
- # length of the string must be 1.
297
- #
298
- #
299
- # See CSV::DEFAULT_OPTIONS for the default settings.
300
- #
301
- # Options cannot be overridden in the instance methods for performance reasons,
302
- # so be sure to set what you want here.
1772
+ # <!--
1773
+ # rdoc-file=lib/csv.rb
1774
+ # - CSV.new(string)
1775
+ # - CSV.new(io)
1776
+ # - CSV.new(string, **options)
1777
+ # - CSV.new(io, **options)
1778
+ # -->
1779
+ # Returns the new CSV object created using `string` or `io` and the specified
1780
+ # `options`.
1781
+ #
1782
+ # * Argument `string` should be a String object; it will be put into a new
1783
+ # StringIO object positioned at the beginning.
1784
+ # * Argument `io` should be an IO object that is:
1785
+ # * Open for reading; on return, the IO object will be closed.
1786
+ # * Positioned at the beginning. To position at the end, for appending,
1787
+ # use method CSV.generate. For any other positioning, pass a preset
1788
+ # StringIO object instead.
1789
+ #
1790
+ # * Argument `options`: See:
1791
+ # * [Options for Parsing](#class-CSV-label-Options+for+Parsing)
1792
+ # * [Options for Generating](#class-CSV-label-Options+for+Generating)
1793
+ #
1794
+ # For performance reasons, the options cannot be overridden in a CSV object,
1795
+ # so those specified here will endure.
1796
+ #
1797
+ #
1798
+ # In addition to the CSV instance methods, several IO methods are delegated. See
1799
+ # [Delegated Methods](#class-CSV-label-Delegated+Methods).
1800
+ #
1801
+ # ---
1802
+ #
1803
+ # Create a CSV object from a String object:
1804
+ # csv = CSV.new('foo,0')
1805
+ # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1806
+ #
1807
+ # Create a CSV object from a File object:
1808
+ # File.write('t.csv', 'foo,0')
1809
+ # csv = CSV.new(File.open('t.csv'))
1810
+ # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1811
+ #
1812
+ # ---
1813
+ #
1814
+ # Raises an exception if the argument is `nil`:
1815
+ # # Raises ArgumentError (Cannot parse nil as CSV):
1816
+ # CSV.new(nil)
1817
+ #
303
1818
  def initialize: (?String | IO | StringIO io, ?::Hash[Symbol, untyped] options) -> void
304
1819
 
305
- # This method can be used to easily parse CSV out of a String. You may either
306
- # provide a `block` which will be called with each row of the String in turn, or
307
- # just use the returned Array of Arrays (when no `block` is given).
1820
+ # <!--
1821
+ # rdoc-file=lib/csv.rb
1822
+ # - parse(string) -> array_of_arrays
1823
+ # - parse(io) -> array_of_arrays
1824
+ # - parse(string, headers: ..., **options) -> csv_table
1825
+ # - parse(io, headers: ..., **options) -> csv_table
1826
+ # - parse(string, **options) {|row| ... }
1827
+ # - parse(io, **options) {|row| ... }
1828
+ # -->
1829
+ # Parses `string` or `io` using the specified `options`.
1830
+ #
1831
+ # * Argument `string` should be a String object; it will be put into a new
1832
+ # StringIO object positioned at the beginning.
1833
+ # * Argument `io` should be an IO object that is:
1834
+ # * Open for reading; on return, the IO object will be closed.
1835
+ # * Positioned at the beginning. To position at the end, for appending,
1836
+ # use method CSV.generate. For any other positioning, pass a preset
1837
+ # StringIO object instead.
1838
+ #
1839
+ # * Argument `options`: see [Options for
1840
+ # Parsing](#class-CSV-label-Options+for+Parsing)
1841
+ #
1842
+ #
1843
+ # ###### Without Option `headers`
1844
+ #
1845
+ # Without {option `headers`[}](#class-CSV-label-Option+headers) case.
1846
+ #
1847
+ # These examples assume prior execution of:
1848
+ # string = "foo,0\nbar,1\nbaz,2\n"
1849
+ # path = 't.csv'
1850
+ # File.write(path, string)
1851
+ #
1852
+ # ---
1853
+ #
1854
+ # With no block given, returns an Array of Arrays formed from the source.
1855
+ #
1856
+ # Parse a String:
1857
+ # a_of_a = CSV.parse(string)
1858
+ # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1859
+ #
1860
+ # Parse an open File:
1861
+ # a_of_a = File.open(path) do |file|
1862
+ # CSV.parse(file)
1863
+ # end
1864
+ # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1865
+ #
1866
+ # ---
1867
+ #
1868
+ # With a block given, calls the block with each parsed row:
308
1869
  #
309
- # You pass your `str` to read from, and an optional `options` containing
310
- # anything CSV::new() understands.
1870
+ # Parse a String:
1871
+ # CSV.parse(string) {|row| p row }
1872
+ #
1873
+ # Output:
1874
+ # ["foo", "0"]
1875
+ # ["bar", "1"]
1876
+ # ["baz", "2"]
1877
+ #
1878
+ # Parse an open File:
1879
+ # File.open(path) do |file|
1880
+ # CSV.parse(file) {|row| p row }
1881
+ # end
1882
+ #
1883
+ # Output:
1884
+ # ["foo", "0"]
1885
+ # ["bar", "1"]
1886
+ # ["baz", "2"]
1887
+ #
1888
+ # ###### With Option `headers`
1889
+ #
1890
+ # With {option `headers`[}](#class-CSV-label-Option+headers) case.
1891
+ #
1892
+ # These examples assume prior execution of:
1893
+ # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
1894
+ # path = 't.csv'
1895
+ # File.write(path, string)
1896
+ #
1897
+ # ---
1898
+ #
1899
+ # With no block given, returns a CSV::Table object formed from the source.
1900
+ #
1901
+ # Parse a String:
1902
+ # csv_table = CSV.parse(string, headers: ['Name', 'Count'])
1903
+ # csv_table # => #<CSV::Table mode:col_or_row row_count:5>
1904
+ #
1905
+ # Parse an open File:
1906
+ # csv_table = File.open(path) do |file|
1907
+ # CSV.parse(file, headers: ['Name', 'Count'])
1908
+ # end
1909
+ # csv_table # => #<CSV::Table mode:col_or_row row_count:4>
1910
+ #
1911
+ # ---
1912
+ #
1913
+ # With a block given, calls the block with each parsed row, which has been
1914
+ # formed into a CSV::Row object:
1915
+ #
1916
+ # Parse a String:
1917
+ # CSV.parse(string, headers: ['Name', 'Count']) {|row| p row }
1918
+ #
1919
+ # Output:
1920
+ # # <CSV::Row "Name":"foo" "Count":"0">
1921
+ # # <CSV::Row "Name":"bar" "Count":"1">
1922
+ # # <CSV::Row "Name":"baz" "Count":"2">
1923
+ #
1924
+ # Parse an open File:
1925
+ # File.open(path) do |file|
1926
+ # CSV.parse(file, headers: ['Name', 'Count']) {|row| p row }
1927
+ # end
1928
+ #
1929
+ # Output:
1930
+ # # <CSV::Row "Name":"foo" "Count":"0">
1931
+ # # <CSV::Row "Name":"bar" "Count":"1">
1932
+ # # <CSV::Row "Name":"baz" "Count":"2">
1933
+ #
1934
+ # ---
1935
+ #
1936
+ # Raises an exception if the argument is not a String object or IO object:
1937
+ # # Raises NoMethodError (undefined method `close' for :foo:Symbol)
1938
+ # CSV.parse(:foo)
311
1939
  #
312
1940
  def self.parse: (String str, ?::Hash[Symbol, untyped] options) ?{ (::Array[String?] arg0) -> void } -> ::Array[::Array[String?]]?
313
1941
 
314
- # This method is a shortcut for converting a single line of a CSV String into an
315
- # Array. Note that if `line` contains multiple rows, anything beyond the first
316
- # row is ignored.
1942
+ # <!--
1943
+ # rdoc-file=lib/csv.rb
1944
+ # - CSV.parse_line(string) -> new_array or nil
1945
+ # - CSV.parse_line(io) -> new_array or nil
1946
+ # - CSV.parse_line(string, **options) -> new_array or nil
1947
+ # - CSV.parse_line(io, **options) -> new_array or nil
1948
+ # - CSV.parse_line(string, headers: true, **options) -> csv_row or nil
1949
+ # - CSV.parse_line(io, headers: true, **options) -> csv_row or nil
1950
+ # -->
1951
+ # Returns the data created by parsing the first line of `string` or `io` using
1952
+ # the specified `options`.
1953
+ #
1954
+ # * Argument `string` should be a String object; it will be put into a new
1955
+ # StringIO object positioned at the beginning.
1956
+ # * Argument `io` should be an IO object that is:
1957
+ # * Open for reading; on return, the IO object will be closed.
1958
+ # * Positioned at the beginning. To position at the end, for appending,
1959
+ # use method CSV.generate. For any other positioning, pass a preset
1960
+ # StringIO object instead.
1961
+ #
1962
+ # * Argument `options`: see [Options for
1963
+ # Parsing](#class-CSV-label-Options+for+Parsing)
1964
+ #
1965
+ #
1966
+ # ###### Without Option `headers`
1967
+ #
1968
+ # Without option `headers`, returns the first row as a new Array.
1969
+ #
1970
+ # These examples assume prior execution of:
1971
+ # string = "foo,0\nbar,1\nbaz,2\n"
1972
+ # path = 't.csv'
1973
+ # File.write(path, string)
1974
+ #
1975
+ # Parse the first line from a String object:
1976
+ # CSV.parse_line(string) # => ["foo", "0"]
317
1977
  #
318
- # The `options` parameter can be anything CSV::new() understands.
1978
+ # Parse the first line from a File object:
1979
+ # File.open(path) do |file|
1980
+ # CSV.parse_line(file) # => ["foo", "0"]
1981
+ # end # => ["foo", "0"]
1982
+ #
1983
+ # Returns `nil` if the argument is an empty String:
1984
+ # CSV.parse_line('') # => nil
1985
+ #
1986
+ # ###### With Option `headers`
1987
+ #
1988
+ # With {option `headers`[}](#class-CSV-label-Option+headers), returns the first
1989
+ # row as a CSV::Row object.
1990
+ #
1991
+ # These examples assume prior execution of:
1992
+ # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
1993
+ # path = 't.csv'
1994
+ # File.write(path, string)
1995
+ #
1996
+ # Parse the first line from a String object:
1997
+ # CSV.parse_line(string, headers: true) # => #<CSV::Row "Name":"foo" "Count":"0">
1998
+ #
1999
+ # Parse the first line from a File object:
2000
+ # File.open(path) do |file|
2001
+ # CSV.parse_line(file, headers: true)
2002
+ # end # => #<CSV::Row "Name":"foo" "Count":"0">
2003
+ #
2004
+ # ---
2005
+ #
2006
+ # Raises an exception if the argument is `nil`:
2007
+ # # Raises ArgumentError (Cannot parse nil as CSV):
2008
+ # CSV.parse_line(nil)
319
2009
  #
320
2010
  def self.parse_line: (String str, ?::Hash[Symbol, untyped] options) -> ::Array[String?]?
321
2011
 
322
- # Slurps the remaining rows and returns an Array of Arrays.
2012
+ # <!--
2013
+ # rdoc-file=lib/csv.rb
2014
+ # - csv.read -> array or csv_table
2015
+ # -->
2016
+ # Forms the remaining rows from `self` into:
2017
+ # * A CSV::Table object, if headers are in use.
2018
+ # * An Array of Arrays, otherwise.
2019
+ #
2020
+ #
2021
+ # The data source must be opened for reading.
2022
+ #
2023
+ # Without headers:
2024
+ # string = "foo,0\nbar,1\nbaz,2\n"
2025
+ # path = 't.csv'
2026
+ # File.write(path, string)
2027
+ # csv = CSV.open(path)
2028
+ # csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
2029
+ #
2030
+ # With headers:
2031
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2032
+ # path = 't.csv'
2033
+ # File.write(path, string)
2034
+ # csv = CSV.open(path, headers: true)
2035
+ # csv.read # => #<CSV::Table mode:col_or_row row_count:4>
323
2036
  #
324
- # The data source must be open for reading.
2037
+ # ---
2038
+ #
2039
+ # Raises an exception if the source is not opened for reading:
2040
+ # string = "foo,0\nbar,1\nbaz,2\n"
2041
+ # csv = CSV.new(string)
2042
+ # csv.close
2043
+ # # Raises IOError (not opened for reading)
2044
+ # csv.read
325
2045
  #
326
2046
  def read: () -> ::Array[::Array[String?]]
327
2047
 
2048
+ # <!--
2049
+ # rdoc-file=lib/csv.rb
2050
+ # - readline()
2051
+ # -->
2052
+ #
328
2053
  def readline: () -> ::Array[String?]?
329
2054
 
330
- # Use to slurp a CSV file into an Array of Arrays. Pass the `path` to the file
331
- # and any `options` CSV::new() understands. This method also understands an
332
- # additional `:encoding` parameter that you can use to specify the Encoding of
333
- # the data in the file to be read. You must provide this unless your data is in
334
- # Encoding::default_external(). CSV will use this to determine how to parse the
335
- # data. You may provide a second Encoding to have the data transcoded as it is
336
- # read. For example, `encoding: "UTF-32BE:UTF-8"` would read UTF-32BE data from
337
- # the file but transcode it to UTF-8 before CSV parses it.
2055
+ # <!--
2056
+ # rdoc-file=lib/csv.rb
2057
+ # - read(source, **options) -> array_of_arrays
2058
+ # - read(source, headers: true, **options) -> csv_table
2059
+ # -->
2060
+ # Opens the given `source` with the given `options` (see CSV.open), reads the
2061
+ # source (see CSV#read), and returns the result, which will be either an Array
2062
+ # of Arrays or a CSV::Table.
2063
+ #
2064
+ # Without headers:
2065
+ # string = "foo,0\nbar,1\nbaz,2\n"
2066
+ # path = 't.csv'
2067
+ # File.write(path, string)
2068
+ # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
2069
+ #
2070
+ # With headers:
2071
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2072
+ # path = 't.csv'
2073
+ # File.write(path, string)
2074
+ # CSV.read(path, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
338
2075
  #
339
2076
  def self.read: (String path, ?::Hash[Symbol, untyped] options) -> ::Array[::Array[String?]]
340
2077
 
341
- # The primary write method for wrapped Strings and IOs, `row` (an Array or
342
- # CSV::Row) is converted to CSV and appended to the data source. When a CSV::Row
343
- # is passed, only the row's fields() are appended to the output.
2078
+ # <!--
2079
+ # rdoc-file=lib/csv.rb
2080
+ # - csv << row -> self
2081
+ # -->
2082
+ # Appends a row to `self`.
344
2083
  #
345
- # The data source must be open for writing.
2084
+ # * Argument `row` must be an Array object or a CSV::Row object.
2085
+ # * The output stream must be open for writing.
2086
+ #
2087
+ #
2088
+ # ---
2089
+ #
2090
+ # Append Arrays:
2091
+ # CSV.generate do |csv|
2092
+ # csv << ['foo', 0]
2093
+ # csv << ['bar', 1]
2094
+ # csv << ['baz', 2]
2095
+ # end # => "foo,0\nbar,1\nbaz,2\n"
2096
+ #
2097
+ # Append CSV::Rows:
2098
+ # headers = []
2099
+ # CSV.generate do |csv|
2100
+ # csv << CSV::Row.new(headers, ['foo', 0])
2101
+ # csv << CSV::Row.new(headers, ['bar', 1])
2102
+ # csv << CSV::Row.new(headers, ['baz', 2])
2103
+ # end # => "foo,0\nbar,1\nbaz,2\n"
2104
+ #
2105
+ # Headers in CSV::Row objects are not appended:
2106
+ # headers = ['Name', 'Count']
2107
+ # CSV.generate do |csv|
2108
+ # csv << CSV::Row.new(headers, ['foo', 0])
2109
+ # csv << CSV::Row.new(headers, ['bar', 1])
2110
+ # csv << CSV::Row.new(headers, ['baz', 2])
2111
+ # end # => "foo,0\nbar,1\nbaz,2\n"
2112
+ #
2113
+ # ---
2114
+ #
2115
+ # Raises an exception if `row` is not an Array or CSV::Row:
2116
+ # CSV.generate do |csv|
2117
+ # # Raises NoMethodError (undefined method `collect' for :foo:Symbol)
2118
+ # csv << :foo
2119
+ # end
2120
+ #
2121
+ # Raises an exception if the output stream is not opened for writing:
2122
+ # path = 't.csv'
2123
+ # File.write(path, '')
2124
+ # File.open(path) do |file|
2125
+ # CSV.open(file) do |csv|
2126
+ # # Raises IOError (not opened for writing)
2127
+ # csv << ['foo', 0]
2128
+ # end
2129
+ # end
346
2130
  #
347
2131
  def <<: (::Array[untyped] | CSV::Row row) -> void
348
2132
 
349
- # This method wraps a String you provide, or an empty default String, in a CSV
350
- # object which is passed to the provided block. You can use the block to append
351
- # CSV rows to the String and when the block exits, the final String will be
352
- # returned.
2133
+ # <!--
2134
+ # rdoc-file=lib/csv.rb
2135
+ # - generate(csv_string, **options) {|csv| ... }
2136
+ # - generate(**options) {|csv| ... }
2137
+ # -->
2138
+ # * Argument `csv_string`, if given, must be a String object; defaults to a
2139
+ # new empty String.
2140
+ # * Arguments `options`, if given, should be generating options. See [Options
2141
+ # for Generating](#class-CSV-label-Options+for+Generating).
2142
+ #
353
2143
  #
354
- # Note that a passed String **is** modified by this method. Call dup() before
355
- # passing if you need a new String.
2144
+ # ---
2145
+ #
2146
+ # Creates a new CSV object via `CSV.new(csv_string, **options)`; calls the block
2147
+ # with the CSV object, which the block may modify; returns the String generated
2148
+ # from the CSV object.
2149
+ #
2150
+ # Note that a passed String **is** modified by this method. Pass
2151
+ # `csv_string`.dup if the String must be preserved.
2152
+ #
2153
+ # This method has one additional option: `:encoding`, which sets the base
2154
+ # Encoding for the output if no no `str` is specified. CSV needs this hint if
2155
+ # you plan to output non-ASCII compatible data.
2156
+ #
2157
+ # ---
2158
+ #
2159
+ # Add lines:
2160
+ # input_string = "foo,0\nbar,1\nbaz,2\n"
2161
+ # output_string = CSV.generate(input_string) do |csv|
2162
+ # csv << ['bat', 3]
2163
+ # csv << ['bam', 4]
2164
+ # end
2165
+ # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
2166
+ # input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
2167
+ # output_string.equal?(input_string) # => true # Same string, modified
2168
+ #
2169
+ # Add lines into new string, preserving old string:
2170
+ # input_string = "foo,0\nbar,1\nbaz,2\n"
2171
+ # output_string = CSV.generate(input_string.dup) do |csv|
2172
+ # csv << ['bat', 3]
2173
+ # csv << ['bam', 4]
2174
+ # end
2175
+ # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
2176
+ # input_string # => "foo,0\nbar,1\nbaz,2\n"
2177
+ # output_string.equal?(input_string) # => false # Different strings
2178
+ #
2179
+ # Create lines from nothing:
2180
+ # output_string = CSV.generate do |csv|
2181
+ # csv << ['foo', 0]
2182
+ # csv << ['bar', 1]
2183
+ # csv << ['baz', 2]
2184
+ # end
2185
+ # output_string # => "foo,0\nbar,1\nbaz,2\n"
2186
+ #
2187
+ # ---
356
2188
  #
357
- # The `options` parameter can be anything CSV::new() understands. This method
358
- # understands an additional `:encoding` parameter when not passed a String to
359
- # set the base Encoding for the output. CSV needs this hint if you plan to
360
- # output non-ASCII compatible data.
2189
+ # Raises an exception if `csv_string` is not a String object:
2190
+ # # Raises TypeError (no implicit conversion of Integer into String)
2191
+ # CSV.generate(0)
361
2192
  #
362
2193
  def self.generate: (?String str, **untyped options) { (CSV csv) -> void } -> String
363
2194
 
364
- # :call-seq:
365
- # csv.each -> enumerator
366
- # csv.each {|row| ...}
367
- #
368
- # Calls the block with each successive row.
369
- # The data source must be opened for reading.
2195
+ # <!--
2196
+ # rdoc-file=lib/csv.rb
2197
+ # - csv.each -> enumerator
2198
+ # - csv.each {|row| ...}
2199
+ # -->
2200
+ # Calls the block with each successive row. The data source must be opened for
2201
+ # reading.
370
2202
  #
371
2203
  # Without headers:
372
- # string = "foo,0\nbar,1\nbaz,2\n"
373
- # csv = CSV.new(string)
374
- # csv.each do |row|
375
- # p row
376
- # end
2204
+ # string = "foo,0\nbar,1\nbaz,2\n"
2205
+ # csv = CSV.new(string)
2206
+ # csv.each do |row|
2207
+ # p row
2208
+ # end
2209
+ #
377
2210
  # Output:
378
- # ["foo", "0"]
379
- # ["bar", "1"]
380
- # ["baz", "2"]
2211
+ # ["foo", "0"]
2212
+ # ["bar", "1"]
2213
+ # ["baz", "2"]
381
2214
  #
382
2215
  # With headers:
383
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
384
- # csv = CSV.new(string, headers: true)
385
- # csv.each do |row|
386
- # p row
387
- # end
2216
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2217
+ # csv = CSV.new(string, headers: true)
2218
+ # csv.each do |row|
2219
+ # p row
2220
+ # end
2221
+ #
388
2222
  # Output:
389
- # <CSV::Row "Name":"foo" "Value":"0">
390
- # <CSV::Row "Name":"bar" "Value":"1">
391
- # <CSV::Row "Name":"baz" "Value":"2">
2223
+ # <CSV::Row "Name":"foo" "Value":"0">
2224
+ # <CSV::Row "Name":"bar" "Value":"1">
2225
+ # <CSV::Row "Name":"baz" "Value":"2">
392
2226
  #
393
2227
  # ---
394
2228
  #
395
2229
  # Raises an exception if the source is not opened for reading:
396
- # string = "foo,0\nbar,1\nbaz,2\n"
397
- # csv = CSV.new(string)
398
- # csv.close
399
- # # Raises IOError (not opened for reading)
400
- # csv.each do |row|
401
- # p row
402
- # end
2230
+ # string = "foo,0\nbar,1\nbaz,2\n"
2231
+ # csv = CSV.new(string)
2232
+ # csv.close
2233
+ # # Raises IOError (not opened for reading)
2234
+ # csv.each do |row|
2235
+ # p row
2236
+ # end
2237
+ #
403
2238
  def each: () -> Enumerator[untyped, Integer]
404
2239
  | () { (untyped) -> void } -> Integer
405
-
406
2240
  end
407
2241
 
408
- # The options used when no overrides are given by calling code. They are:
409
- #
410
- # **`:col_sep`**
411
- # : `","`
412
- # **`:row_sep`**
413
- # : `:auto`
414
- # **`:quote_char`**
415
- # : `'"'`
416
- # **`:field_size_limit`**
417
- # : `nil`
418
- # **`:converters`**
419
- # : `nil`
420
- # **`:unconverted_fields`**
421
- # : `nil`
422
- # **`:headers`**
423
- # : `false`
424
- # **`:return_headers`**
425
- # : `false`
426
- # **`:header_converters`**
427
- # : `nil`
428
- # **`:skip_blanks`**
429
- # : `false`
430
- # **`:force_quotes`**
431
- # : `false`
432
- # **`:skip_lines`**
433
- # : `nil`
434
- # **`:liberal_parsing`**
435
- # : `false`
436
- # **`:quote_empty`**
437
- # : `true`
438
- #
2242
+ # <!-- rdoc-file=lib/csv.rb -->
2243
+ # Default values for method options.
439
2244
  #
440
2245
  CSV::DEFAULT_OPTIONS: ::Hash[untyped, untyped]
441
2246
 
2247
+ # <!-- rdoc-file=lib/csv/version.rb -->
442
2248
  # The version of the installed library.
443
2249
  #
444
2250
  CSV::VERSION: String
445
2251
 
2252
+ # <!-- rdoc-file=lib/csv/row.rb -->
446
2253
  # A CSV::Row is part Array and part Hash. It retains an order for the fields and
447
2254
  # allows duplicates just as an Array would, but also allows you to access fields
448
2255
  # by name just as you could if they were in a Hash.
@@ -454,52 +2261,189 @@ class CSV::Row < Object
454
2261
  include Enumerable[Array[String]]
455
2262
  extend Forwardable
456
2263
 
457
- # If a two-element Array is provided, it is assumed to be a header and field and
458
- # the pair is appended. A Hash works the same way with the key being the header
459
- # and the value being the field. Anything else is assumed to be a lone field
460
- # which is appended with a `nil` header.
461
- #
462
- # This method returns the row for chaining.
2264
+ # <!--
2265
+ # rdoc-file=lib/csv/row.rb
2266
+ # - row << [header, value] -> self
2267
+ # - row << hash -> self
2268
+ # - row << value -> self
2269
+ # -->
2270
+ # Adds a field to `self`; returns `self`:
2271
+ #
2272
+ # If the argument is a 2-element Array `[header, value]`, a field is added with
2273
+ # the given `header` and `value`:
2274
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2275
+ # table = CSV.parse(source, headers: true)
2276
+ # row = table[0]
2277
+ # row << ['NAME', 'Bat']
2278
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
2279
+ #
2280
+ # If the argument is a Hash, each `key-value` pair is added as a field with
2281
+ # header `key` and value `value`.
2282
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2283
+ # table = CSV.parse(source, headers: true)
2284
+ # row = table[0]
2285
+ # row << {NAME: 'Bat', name: 'Bam'}
2286
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
2287
+ #
2288
+ # Otherwise, the given `value` is added as a field with no header.
2289
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2290
+ # table = CSV.parse(source, headers: true)
2291
+ # row = table[0]
2292
+ # row << 'Bag'
2293
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
463
2294
  #
464
2295
  def <<: (untyped arg) -> untyped
465
2296
 
2297
+ # <!--
2298
+ # rdoc-file=lib/csv/row.rb
2299
+ # - ==(other)
2300
+ # -->
466
2301
  # Returns `true` if this row contains the same headers and fields in the same
467
2302
  # order as `other`.
468
2303
  #
469
2304
  def ==: (untyped other) -> bool
470
2305
 
2306
+ # <!--
2307
+ # rdoc-file=lib/csv/row.rb
2308
+ # - [](header_or_index, minimum_index = 0)
2309
+ # -->
2310
+ #
471
2311
  alias [] field
472
2312
 
473
- # Looks up the field by the semantics described in CSV::Row.field() and assigns
474
- # the `value`.
2313
+ # <!--
2314
+ # rdoc-file=lib/csv/row.rb
2315
+ # - row[index] = value -> value
2316
+ # - row[header, offset] = value -> value
2317
+ # - row[header] = value -> value
2318
+ # -->
2319
+ # Assigns the field value for the given `index` or `header`; returns `value`.
2320
+ #
2321
+ # ---
2322
+ #
2323
+ # Assign field value by Integer index:
2324
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2325
+ # table = CSV.parse(source, headers: true)
2326
+ # row = table[0]
2327
+ # row[0] = 'Bat'
2328
+ # row[1] = 3
2329
+ # row # => #<CSV::Row "Name":"Bat" "Value":3>
2330
+ #
2331
+ # Counts backward from the last column if `index` is negative:
2332
+ # row[-1] = 4
2333
+ # row[-2] = 'Bam'
2334
+ # row # => #<CSV::Row "Name":"Bam" "Value":4>
2335
+ #
2336
+ # Extends the row with `nil:nil` if positive `index` is not in the row:
2337
+ # row[4] = 5
2338
+ # row # => #<CSV::Row "Name":"bad" "Value":4 nil:nil nil:nil nil:5>
2339
+ #
2340
+ # Raises IndexError if negative `index` is too small (too far from zero).
475
2341
  #
476
- # Assigning past the end of the row with an index will set all pairs between to
477
- # `[nil, nil]`. Assigning to an unused header appends the new pair.
2342
+ # ---
2343
+ #
2344
+ # Assign field value by header (first found):
2345
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2346
+ # table = CSV.parse(source, headers: true)
2347
+ # row = table[0]
2348
+ # row['Name'] = 'Bat'
2349
+ # row # => #<CSV::Row "Name":"Bat" "Name":"Bar" "Name":"Baz">
2350
+ #
2351
+ # Assign field value by header, ignoring `offset` leading fields:
2352
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2353
+ # table = CSV.parse(source, headers: true)
2354
+ # row = table[0]
2355
+ # row['Name', 2] = 4
2356
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":4>
2357
+ #
2358
+ # Append new field by (new) header:
2359
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2360
+ # table = CSV.parse(source, headers: true)
2361
+ # row = table[0]
2362
+ # row['New'] = 6
2363
+ # row# => #<CSV::Row "Name":"foo" "Value":"0" "New":6>
478
2364
  #
479
2365
  def []=: (*untyped args) -> untyped
480
2366
 
481
- # Removes a pair from the row by `header` or `index`. The pair is located as
482
- # described in CSV::Row.field(). The deleted pair is returned, or `nil` if a
483
- # pair could not be found.
2367
+ # <!--
2368
+ # rdoc-file=lib/csv/row.rb
2369
+ # - delete(index) -> [header, value] or nil
2370
+ # - delete(header) -> [header, value] or empty_array
2371
+ # - delete(header, offset) -> [header, value] or empty_array
2372
+ # -->
2373
+ # Removes a specified field from `self`; returns the 2-element Array `[header,
2374
+ # value]` if the field exists.
2375
+ #
2376
+ # If an Integer argument `index` is given, removes and returns the field at
2377
+ # offset `index`, or returns `nil` if the field does not exist:
2378
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2379
+ # table = CSV.parse(source, headers: true)
2380
+ # row = table[0]
2381
+ # row.delete(1) # => ["Name", "Bar"]
2382
+ # row.delete(50) # => nil
2383
+ #
2384
+ # Otherwise, if the single argument `header` is given, removes and returns the
2385
+ # first-found field with the given header, of returns a new empty Array if the
2386
+ # field does not exist:
2387
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2388
+ # table = CSV.parse(source, headers: true)
2389
+ # row = table[0]
2390
+ # row.delete('Name') # => ["Name", "Foo"]
2391
+ # row.delete('NAME') # => []
2392
+ #
2393
+ # If argument `header` and Integer argument `offset` are given, removes and
2394
+ # returns the first-found field with the given header whose `index` is at least
2395
+ # as large as `offset`:
2396
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2397
+ # table = CSV.parse(source, headers: true)
2398
+ # row = table[0]
2399
+ # row.delete('Name', 1) # => ["Name", "Bar"]
2400
+ # row.delete('NAME', 1) # => []
484
2401
  #
485
2402
  def delete: (untyped header_or_index, ?untyped minimum_index) -> untyped
486
2403
 
487
- # The provided `block` is passed a header and field for each pair in the row and
488
- # expected to return `true` or `false`, depending on whether the pair should be
489
- # deleted.
2404
+ # <!--
2405
+ # rdoc-file=lib/csv/row.rb
2406
+ # - row.delete_if {|header, value| ... } -> self
2407
+ # -->
2408
+ # Removes fields from `self` as selected by the block; returns `self`.
490
2409
  #
491
- # This method returns the row for chaining.
2410
+ # Removes each field for which the block returns a truthy value:
2411
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2412
+ # table = CSV.parse(source, headers: true)
2413
+ # row = table[0]
2414
+ # row.delete_if {|header, value| value.start_with?('B') } # => true
2415
+ # row # => #<CSV::Row "Name":"Foo">
2416
+ # row.delete_if {|header, value| header.start_with?('B') } # => false
492
2417
  #
493
- # If no block is given, an Enumerator is returned.
2418
+ # If no block is given, returns a new Enumerator:
2419
+ # row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
494
2420
  #
495
2421
  def delete_if: () { (*untyped) -> untyped } -> untyped
496
2422
 
497
- # Extracts the nested value specified by the sequence of `index` or `header`
498
- # objects by calling dig at each step, returning nil if any intermediate step is
499
- # nil.
2423
+ # <!--
2424
+ # rdoc-file=lib/csv/row.rb
2425
+ # - row.dig(index_or_header, *identifiers) -> object
2426
+ # -->
2427
+ # Finds and returns the object in nested object that is specified by
2428
+ # `index_or_header` and `specifiers`.
2429
+ #
2430
+ # The nested objects may be instances of various classes. See [Dig
2431
+ # Methods](https://docs.ruby-lang.org/en/master/doc/dig_methods_rdoc.html).
2432
+ #
2433
+ # Examples:
2434
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2435
+ # table = CSV.parse(source, headers: true)
2436
+ # row = table[0]
2437
+ # row.dig(1) # => "0"
2438
+ # row.dig('Value') # => "0"
2439
+ # row.dig(5) # => nil
500
2440
  #
501
2441
  def dig: (untyped index_or_header, *untyped indexes) -> untyped
502
2442
 
2443
+ # <!--
2444
+ # rdoc-file=lib/csv/row.rb
2445
+ # - each(&block)
2446
+ # -->
503
2447
  # Yields each pair of the row as header and field tuples (much like iterating
504
2448
  # over a Hash). This method returns the row for chaining.
505
2449
  #
@@ -510,112 +2454,326 @@ class CSV::Row < Object
510
2454
  def each: () -> Enumerator[Array[String], self]
511
2455
  | () { (Array[String]) -> void } -> self
512
2456
 
2457
+ # <!--
2458
+ # rdoc-file=lib/csv/row.rb
2459
+ # - each_pair(&block)
2460
+ # -->
2461
+ #
513
2462
  alias each_pair each
514
2463
 
515
2464
  def empty?: (*untyped args) { (*untyped) -> untyped } -> bool
516
2465
 
517
- # This method will fetch the field value by `header`. It has the same behavior
518
- # as Hash#fetch: if there is a field with the given `header`, its value is
519
- # returned. Otherwise, if a block is given, it is yielded the `header` and its
520
- # result is returned; if a `default` is given as the second argument, it is
521
- # returned; otherwise a KeyError is raised.
2466
+ # <!--
2467
+ # rdoc-file=lib/csv/row.rb
2468
+ # - fetch(header)
2469
+ # - fetch(header, default)
2470
+ # - fetch(header) {|row| ... }
2471
+ # -->
2472
+ # Returns the field value as specified by `header`.
2473
+ #
2474
+ # ---
2475
+ #
2476
+ # With the single argument `header`, returns the field value for that header
2477
+ # (first found):
2478
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2479
+ # table = CSV.parse(source, headers: true)
2480
+ # row = table[0]
2481
+ # row.fetch('Name') # => "Foo"
2482
+ #
2483
+ # Raises exception `KeyError` if the header does not exist.
2484
+ #
2485
+ # ---
2486
+ #
2487
+ # With arguments `header` and `default` given, returns the field value for the
2488
+ # header (first found) if the header exists, otherwise returns `default`:
2489
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2490
+ # table = CSV.parse(source, headers: true)
2491
+ # row = table[0]
2492
+ # row.fetch('Name', '') # => "Foo"
2493
+ # row.fetch(:nosuch, '') # => ""
2494
+ #
2495
+ # ---
2496
+ #
2497
+ # With argument `header` and a block given, returns the field value for the
2498
+ # header (first found) if the header exists; otherwise calls the block and
2499
+ # returns its return value:
2500
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2501
+ # table = CSV.parse(source, headers: true)
2502
+ # row = table[0]
2503
+ # row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo"
2504
+ # row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'"
522
2505
  #
523
2506
  def fetch: (untyped header, *untyped varargs) ?{ (*untyped) -> untyped } -> untyped
524
2507
 
525
- # This method will return the field value by `header` or `index`. If a field is
526
- # not found, `nil` is returned.
2508
+ # <!--
2509
+ # rdoc-file=lib/csv/row.rb
2510
+ # - field(index)
2511
+ # - field(header)
2512
+ # - field(header, offset)
2513
+ # -->
2514
+ # Returns the field value for the given `index` or `header`.
2515
+ #
2516
+ # ---
2517
+ #
2518
+ # Fetch field value by Integer index:
2519
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2520
+ # table = CSV.parse(source, headers: true)
2521
+ # row = table[0]
2522
+ # row.field(0) # => "foo"
2523
+ # row.field(1) # => "bar"
2524
+ #
2525
+ # Counts backward from the last column if `index` is negative:
2526
+ # row.field(-1) # => "0"
2527
+ # row.field(-2) # => "foo"
2528
+ #
2529
+ # Returns `nil` if `index` is out of range:
2530
+ # row.field(2) # => nil
2531
+ # row.field(-3) # => nil
527
2532
  #
528
- # When provided, `offset` ensures that a header match occurs on or later than
529
- # the `offset` index. You can use this to find duplicate headers, without
530
- # resorting to hard-coding exact indices.
2533
+ # ---
2534
+ #
2535
+ # Fetch field value by header (first found):
2536
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2537
+ # table = CSV.parse(source, headers: true)
2538
+ # row = table[0]
2539
+ # row.field('Name') # => "Foo"
2540
+ #
2541
+ # Fetch field value by header, ignoring `offset` leading fields:
2542
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2543
+ # table = CSV.parse(source, headers: true)
2544
+ # row = table[0]
2545
+ # row.field('Name', 2) # => "Baz"
2546
+ #
2547
+ # Returns `nil` if the header does not exist.
531
2548
  #
532
2549
  def field: (untyped header_or_index, ?untyped minimum_index) -> untyped
533
2550
 
2551
+ # <!--
2552
+ # rdoc-file=lib/csv/row.rb
2553
+ # - field?(data)
2554
+ # -->
534
2555
  # Returns `true` if `data` matches a field in this row, and `false` otherwise.
535
2556
  #
536
2557
  def field?: (untyped data) -> bool
537
2558
 
538
- # Returns `true` if this is a field row.
2559
+ # <!--
2560
+ # rdoc-file=lib/csv/row.rb
2561
+ # - row.field_row? -> true or false
2562
+ # -->
2563
+ # Returns `true` if this is a field row, `false` otherwise.
539
2564
  #
540
2565
  def field_row?: () -> bool
541
2566
 
542
- # This method accepts any number of arguments which can be headers, indices,
543
- # Ranges of either, or two-element Arrays containing a header and offset. Each
544
- # argument will be replaced with a field lookup as described in
545
- # CSV::Row.field().
2567
+ # <!--
2568
+ # rdoc-file=lib/csv/row.rb
2569
+ # - self.fields(*specifiers)
2570
+ # -->
2571
+ # Returns field values per the given `specifiers`, which may be any mixture of:
2572
+ # * Integer index.
2573
+ # * Range of Integer indexes.
2574
+ # * 2-element Array containing a header and offset.
2575
+ # * Header.
2576
+ # * Range of headers.
2577
+ #
2578
+ #
2579
+ # For `specifier` in one of the first four cases above, returns the result of
2580
+ # `self.field(specifier)`; see #field.
2581
+ #
2582
+ # Although there may be any number of `specifiers`, the examples here will
2583
+ # illustrate one at a time.
546
2584
  #
547
- # If called with no arguments, all fields are returned.
2585
+ # When the specifier is an Integer `index`, returns `self.field(index)`L
2586
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2587
+ # table = CSV.parse(source, headers: true)
2588
+ # row = table[0]
2589
+ # row.fields(1) # => ["Bar"]
2590
+ #
2591
+ # When the specifier is a Range of Integers `range`, returns
2592
+ # `self.field(range)`:
2593
+ # row.fields(1..2) # => ["Bar", "Baz"]
2594
+ #
2595
+ # When the specifier is a 2-element Array `array`, returns `self.field(array)`L
2596
+ # row.fields('Name', 1) # => ["Foo", "Bar"]
2597
+ #
2598
+ # When the specifier is a header `header`, returns `self.field(header)`L
2599
+ # row.fields('Name') # => ["Foo"]
2600
+ #
2601
+ # When the specifier is a Range of headers `range`, forms a new Range
2602
+ # `new_range` from the indexes of `range.start` and `range.end`, and returns
2603
+ # `self.field(new_range)`:
2604
+ # source = "Name,NAME,name\nFoo,Bar,Baz\n"
2605
+ # table = CSV.parse(source, headers: true)
2606
+ # row = table[0]
2607
+ # row.fields('Name'..'NAME') # => ["Foo", "Bar"]
2608
+ #
2609
+ # Returns all fields if no argument given:
2610
+ # row.fields # => ["Foo", "Bar", "Baz"]
548
2611
  #
549
2612
  def fields: (*untyped headers_and_or_indices) -> untyped
550
2613
 
551
- # Returns `true` if there is a field with the given `header`.
2614
+ # <!--
2615
+ # rdoc-file=lib/csv/row.rb
2616
+ # - row.has_key?(header)
2617
+ # -->
2618
+ # Returns `true` if there is a field with the given `header`, `false` otherwise.
552
2619
  #
553
2620
  def has_key?: (untyped header) -> bool
554
2621
 
2622
+ # <!--
2623
+ # rdoc-file=lib/csv/row.rb
2624
+ # - header?(header)
2625
+ # -->
2626
+ #
555
2627
  alias header? has_key?
556
2628
 
557
- # Returns `true` if this is a header row.
2629
+ # <!--
2630
+ # rdoc-file=lib/csv/row.rb
2631
+ # - row.header_row? -> true or false
2632
+ # -->
2633
+ # Returns `true` if this is a header row, `false` otherwise.
558
2634
  #
559
2635
  def header_row?: () -> bool
560
2636
 
561
- # Returns the headers of this row.
2637
+ # <!--
2638
+ # rdoc-file=lib/csv/row.rb
2639
+ # - row.headers
2640
+ # -->
2641
+ # Returns the headers for this row:
2642
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2643
+ # table = CSV.parse(source, headers: true)
2644
+ # row = table.first
2645
+ # row.headers # => ["Name", "Value"]
562
2646
  #
563
2647
  def headers: () -> untyped
564
2648
 
2649
+ # <!--
2650
+ # rdoc-file=lib/csv/row.rb
2651
+ # - include?(header)
2652
+ # -->
2653
+ #
565
2654
  alias include? has_key?
566
2655
 
2656
+ # <!--
2657
+ # rdoc-file=lib/csv/row.rb
2658
+ # - index( header )
2659
+ # - index( header, offset )
2660
+ # -->
567
2661
  # This method will return the index of a field with the provided `header`. The
568
2662
  # `offset` can be used to locate duplicate header names, as described in
569
2663
  # CSV::Row.field().
570
2664
  #
571
2665
  def index: (untyped header, ?untyped minimum_index) -> untyped
572
2666
 
573
- # A summary of fields, by header, in an ASCII compatible String.
2667
+ # <!--
2668
+ # rdoc-file=lib/csv/row.rb
2669
+ # - row.inspect -> string
2670
+ # -->
2671
+ # Returns an ASCII-compatible String showing:
2672
+ # * Class CSV::Row.
2673
+ # * Header-value pairs.
2674
+ #
2675
+ # Example:
2676
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2677
+ # table = CSV.parse(source, headers: true)
2678
+ # row = table[0]
2679
+ # row.inspect # => "#<CSV::Row \"Name\":\"foo\" \"Value\":\"0\">"
574
2680
  #
575
2681
  def inspect: () -> String
576
2682
 
2683
+ # <!--
2684
+ # rdoc-file=lib/csv/row.rb
2685
+ # - key?(header)
2686
+ # -->
2687
+ #
577
2688
  alias key? has_key?
578
2689
 
579
2690
  def length: (*untyped args) { (*untyped) -> untyped } -> untyped
580
2691
 
2692
+ # <!--
2693
+ # rdoc-file=lib/csv/row.rb
2694
+ # - member?(header)
2695
+ # -->
2696
+ #
581
2697
  alias member? has_key?
582
2698
 
583
- # A shortcut for appending multiple fields. Equivalent to:
584
- #
585
- # args.each { |arg| csv_row << arg }
586
- #
587
- # This method returns the row for chaining.
2699
+ # <!--
2700
+ # rdoc-file=lib/csv/row.rb
2701
+ # - row.push(*values) ->self
2702
+ # -->
2703
+ # Appends each of the given `values` to `self` as a field; returns `self`:
2704
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2705
+ # table = CSV.parse(source, headers: true)
2706
+ # row = table[0]
2707
+ # row.push('Bat', 'Bam')
2708
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
588
2709
  #
589
2710
  def push: (*untyped args) -> untyped
590
2711
 
591
2712
  def size: (*untyped args) { (*untyped) -> untyped } -> untyped
592
2713
 
593
- # Returns the row as a CSV String. Headers are not used. Equivalent to:
594
- #
595
- # csv_row.fields.to_csv( options )
2714
+ # <!--
2715
+ # rdoc-file=lib/csv/row.rb
2716
+ # - row.to_csv -> csv_string
2717
+ # -->
2718
+ # Returns the row as a CSV String. Headers are not included:
2719
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2720
+ # table = CSV.parse(source, headers: true)
2721
+ # row = table[0]
2722
+ # row.to_csv # => "foo,0\n"
596
2723
  #
597
2724
  def to_csv: (**untyped) -> untyped
598
2725
 
599
- # Collapses the row into a simple Hash. Be warned that this discards field order
600
- # and clobbers duplicate fields.
2726
+ # <!--
2727
+ # rdoc-file=lib/csv/row.rb
2728
+ # - row.to_h -> hash
2729
+ # -->
2730
+ # Returns the new Hash formed by adding each header-value pair in `self` as a
2731
+ # key-value pair in the Hash.
2732
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2733
+ # table = CSV.parse(source, headers: true)
2734
+ # row = table[0]
2735
+ # row.to_h # => {"Name"=>"foo", "Value"=>"0"}
2736
+ #
2737
+ # Header order is preserved, but repeated headers are ignored:
2738
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2739
+ # table = CSV.parse(source, headers: true)
2740
+ # row = table[0]
2741
+ # row.to_h # => {"Name"=>"Foo"}
601
2742
  #
602
2743
  def to_h: () -> untyped
603
2744
 
2745
+ # <!--
2746
+ # rdoc-file=lib/csv/row.rb
2747
+ # - to_hash()
2748
+ # -->
2749
+ #
604
2750
  alias to_hash to_h
605
2751
 
2752
+ # <!--
2753
+ # rdoc-file=lib/csv/row.rb
2754
+ # - to_s(**options)
2755
+ # -->
2756
+ #
606
2757
  alias to_s to_csv
607
2758
 
2759
+ # <!--
2760
+ # rdoc-file=lib/csv/row.rb
2761
+ # - values_at(*headers_and_or_indices)
2762
+ # -->
2763
+ #
608
2764
  alias values_at fields
609
2765
  end
610
2766
 
611
2767
  class CSV::FieldInfo < Struct[untyped]
612
2768
  end
613
2769
 
2770
+ # <!-- rdoc-file=lib/csv.rb -->
614
2771
  # The error thrown when the parser encounters illegal CSV formatting.
615
2772
  #
616
2773
  class CSV::MalformedCSVError < RuntimeError
617
2774
  end
618
2775
 
2776
+ # <!-- rdoc-file=lib/csv/table.rb -->
619
2777
  # A CSV::Table is a two-dimensional data structure for representing CSV
620
2778
  # documents. Tables allow you to work with the data by row or column, manipulate
621
2779
  # the data, and even convert the results back to CSV, if needed.
@@ -627,6 +2785,10 @@ class CSV::Table[out Elem] < Object
627
2785
  include Enumerable[untyped]
628
2786
  extend Forwardable
629
2787
 
2788
+ # <!--
2789
+ # rdoc-file=lib/csv/table.rb
2790
+ # - new(array_of_rows, headers: nil)
2791
+ # -->
630
2792
  # Constructs a new CSV::Table from `array_of_rows`, which are expected to be
631
2793
  # CSV::Row objects. All rows are assumed to have the same headers.
632
2794
  #
@@ -642,27 +2804,142 @@ class CSV::Table[out Elem] < Object
642
2804
  #
643
2805
  def initialize: (untyped array_of_rows, ?headers: untyped) -> untyped
644
2806
 
645
- # Adds a new row to the bottom end of this table. You can provide an Array,
646
- # which will be converted to a CSV::Row (inheriting the table's headers()), or a
647
- # CSV::Row.
648
- #
649
- # This method returns the table for chaining.
2807
+ # <!--
2808
+ # rdoc-file=lib/csv/table.rb
2809
+ # - table << row_or_array -> self
2810
+ # -->
2811
+ # If `row_or_array` is a CSV::Row object, it is appended to the table:
2812
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2813
+ # table = CSV.parse(source, headers: true)
2814
+ # table << CSV::Row.new(table.headers, ['bat', 3])
2815
+ # table[3] # => #<CSV::Row "Name":"bat" "Value":3>
2816
+ #
2817
+ # If `row_or_array` is an Array, it is used to create a new CSV::Row object
2818
+ # which is then appended to the table:
2819
+ # table << ['bam', 4]
2820
+ # table[4] # => #<CSV::Row "Name":"bam" "Value":4>
650
2821
  #
651
2822
  def <<: (untyped row_or_array) -> untyped
652
2823
 
653
- # Returns `true` if all rows of this table ==() `other`'s rows.
2824
+ # <!--
2825
+ # rdoc-file=lib/csv/table.rb
2826
+ # - ==(other)
2827
+ # -->
2828
+ # Returns `true` if all each row of `self` `==` the corresponding row of
2829
+ # `other_table`, otherwise, `false`.
2830
+ #
2831
+ # The access mode does no affect the result.
2832
+ #
2833
+ # Equal tables:
2834
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2835
+ # table = CSV.parse(source, headers: true)
2836
+ # other_table = CSV.parse(source, headers: true)
2837
+ # table == other_table # => true
2838
+ #
2839
+ # Different row count:
2840
+ # other_table.delete(2)
2841
+ # table == other_table # => false
2842
+ #
2843
+ # Different last row:
2844
+ # other_table << ['bat', 3]
2845
+ # table == other_table # => false
654
2846
  #
655
2847
  def ==: (untyped other) -> bool
656
2848
 
657
- # In the default mixed mode, this method returns rows for index access and
658
- # columns for header access. You can force the index association by first
659
- # calling by_col!() or by_row!().
2849
+ # <!--
2850
+ # rdoc-file=lib/csv/table.rb
2851
+ # - table[n] -> row
2852
+ # - table[range] -> array_of_rows
2853
+ # - table[header] -> array_of_fields
2854
+ # -->
2855
+ # Returns data from the table; does not modify the table.
2856
+ #
2857
+ # ---
2858
+ #
2859
+ # The expression `table[n]`, where `n` is a non-negative Integer, returns the
2860
+ # +n+th row of the table, if that row exists, and if the access mode is `:row`
2861
+ # or `:col_or_row`:
2862
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2863
+ # table = CSV.parse(source, headers: true)
2864
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
2865
+ # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
2866
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
2867
+ # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
2868
+ #
2869
+ # Counts backward from the last row if `n` is negative:
2870
+ # table[-1] # => #<CSV::Row "Name":"baz" "Value":"2">
2871
+ #
2872
+ # Returns `nil` if `n` is too large or too small:
2873
+ # table[4] # => nil
2874
+ # table[-4] => nil
2875
+ #
2876
+ # Raises an exception if the access mode is `:row` and `n` is not an
2877
+ # [Integer-convertible
2878
+ # object](https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#lab
2879
+ # el-Integer-Convertible+Objects).
2880
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
2881
+ # # Raises TypeError (no implicit conversion of String into Integer):
2882
+ # table['Name']
2883
+ #
2884
+ # ---
2885
+ #
2886
+ # The expression `table[range]`, where `range` is a Range object, returns rows
2887
+ # from the table, beginning at row `range.first`, if those rows exist, and if
2888
+ # the access mode is `:row` or `:col_or_row`:
2889
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2890
+ # table = CSV.parse(source, headers: true)
2891
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
2892
+ # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
2893
+ # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
2894
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
2895
+ # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
2896
+ # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
2897
+ #
2898
+ # If there are too few rows, returns all from `range.first` to the end:
2899
+ # rows = table[1..50] # => #<CSV::Row "Name":"bar" "Value":"1">
2900
+ # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
2901
+ #
2902
+ # Special case: if `range.start == table.size`, returns an empty Array:
2903
+ # table[table.size..50] # => []
2904
+ #
2905
+ # If `range.end` is negative, calculates the ending index from the end:
2906
+ # rows = table[0..-1]
2907
+ # rows # => [#<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
660
2908
  #
661
- # Columns are returned as an Array of values. Altering that Array has no effect
662
- # on the table.
2909
+ # If `range.start` is negative, calculates the starting index from the end:
2910
+ # rows = table[-1..2]
2911
+ # rows # => [#<CSV::Row "Name":"baz" "Value":"2">]
2912
+ #
2913
+ # If `range.start` is larger than `table.size`, returns `nil`:
2914
+ # table[4..4] # => nil
2915
+ #
2916
+ # ---
2917
+ #
2918
+ # The expression `table[header]`, where `header` is a String, returns column
2919
+ # values (Array of Strings) if the column exists and if the access mode is
2920
+ # `:col` or `:col_or_row`:
2921
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2922
+ # table = CSV.parse(source, headers: true)
2923
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
2924
+ # table['Name'] # => ["foo", "bar", "baz"]
2925
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
2926
+ # col = table['Name']
2927
+ # col # => ["foo", "bar", "baz"]
2928
+ #
2929
+ # Modifying the returned column values does not modify the table:
2930
+ # col[0] = 'bat'
2931
+ # col # => ["bat", "bar", "baz"]
2932
+ # table['Name'] # => ["foo", "bar", "baz"]
2933
+ #
2934
+ # Returns an Array of `nil` values if there is no such column:
2935
+ # table['Nosuch'] # => [nil, nil, nil]
663
2936
  #
664
2937
  def []: (untyped index_or_header) -> untyped
665
2938
 
2939
+ # <!--
2940
+ # rdoc-file=lib/csv/table.rb
2941
+ # - []=(index_or_header, value)
2942
+ # -->
666
2943
  # In the default mixed mode, this method assigns rows for index access and
667
2944
  # columns for header access. You can force the index association by first
668
2945
  # calling by_col!() or by_row!().
@@ -680,6 +2957,10 @@ class CSV::Table[out Elem] < Object
680
2957
  #
681
2958
  def []=: (untyped index_or_header, untyped value) -> untyped
682
2959
 
2960
+ # <!--
2961
+ # rdoc-file=lib/csv/table.rb
2962
+ # - by_col()
2963
+ # -->
683
2964
  # Returns a duplicate table object, in column mode. This is handy for chaining
684
2965
  # in a single call without changing the table mode, but be aware that this
685
2966
  # method can consume a fair amount of memory for bigger data sets.
@@ -689,6 +2970,10 @@ class CSV::Table[out Elem] < Object
689
2970
  #
690
2971
  def by_col: () -> untyped
691
2972
 
2973
+ # <!--
2974
+ # rdoc-file=lib/csv/table.rb
2975
+ # - by_col!()
2976
+ # -->
692
2977
  # Switches the mode of this table to column mode. All calls to indexing and
693
2978
  # iteration methods will work with columns until the mode is changed again.
694
2979
  #
@@ -696,6 +2981,10 @@ class CSV::Table[out Elem] < Object
696
2981
  #
697
2982
  def by_col!: () -> untyped
698
2983
 
2984
+ # <!--
2985
+ # rdoc-file=lib/csv/table.rb
2986
+ # - by_col_or_row()
2987
+ # -->
699
2988
  # Returns a duplicate table object, in mixed mode. This is handy for chaining in
700
2989
  # a single call without changing the table mode, but be aware that this method
701
2990
  # can consume a fair amount of memory for bigger data sets.
@@ -705,6 +2994,10 @@ class CSV::Table[out Elem] < Object
705
2994
  #
706
2995
  def by_col_or_row: () -> untyped
707
2996
 
2997
+ # <!--
2998
+ # rdoc-file=lib/csv/table.rb
2999
+ # - by_col_or_row!()
3000
+ # -->
708
3001
  # Switches the mode of this table to mixed mode. All calls to indexing and
709
3002
  # iteration methods will use the default intelligent indexing system until the
710
3003
  # mode is changed again. In mixed mode an index is assumed to be a row reference
@@ -714,6 +3007,10 @@ class CSV::Table[out Elem] < Object
714
3007
  #
715
3008
  def by_col_or_row!: () -> untyped
716
3009
 
3010
+ # <!--
3011
+ # rdoc-file=lib/csv/table.rb
3012
+ # - by_row()
3013
+ # -->
717
3014
  # Returns a duplicate table object, in row mode. This is handy for chaining in
718
3015
  # a single call without changing the table mode, but be aware that this method
719
3016
  # can consume a fair amount of memory for bigger data sets.
@@ -723,6 +3020,10 @@ class CSV::Table[out Elem] < Object
723
3020
  #
724
3021
  def by_row: () -> untyped
725
3022
 
3023
+ # <!--
3024
+ # rdoc-file=lib/csv/table.rb
3025
+ # - by_row!()
3026
+ # -->
726
3027
  # Switches the mode of this table to row mode. All calls to indexing and
727
3028
  # iteration methods will work with rows until the mode is changed again.
728
3029
  #
@@ -730,36 +3031,121 @@ class CSV::Table[out Elem] < Object
730
3031
  #
731
3032
  def by_row!: () -> untyped
732
3033
 
733
- # Removes and returns the indicated columns or rows. In the default mixed mode
734
- # indices refer to rows and everything else is assumed to be a column headers.
735
- # Use by_col!() or by_row!() to force the lookup.
3034
+ # <!--
3035
+ # rdoc-file=lib/csv/table.rb
3036
+ # - table.delete(*indexes) -> deleted_values
3037
+ # - table.delete(*headers) -> deleted_values
3038
+ # -->
3039
+ # If the access mode is `:row` or `:col_or_row`, and each argument is either an
3040
+ # Integer or a Range, returns deleted rows. Otherwise, returns deleted columns
3041
+ # data.
736
3042
  #
737
- def delete: (*untyped indexes_or_headers) -> untyped
738
-
739
- # Removes any column or row for which the block returns `true`. In the default
740
- # mixed mode or row mode, iteration is the standard row major walking of rows.
741
- # In column mode, iteration will `yield` two element tuples containing the
742
- # column name and an Array of values for that column.
3043
+ # In either case, the returned values are in the order specified by the
3044
+ # arguments. Arguments may be repeated.
743
3045
  #
744
- # This method returns the table for chaining.
3046
+ # ---
745
3047
  #
746
- # If no block is given, an Enumerator is returned.
3048
+ # Returns rows as an Array of CSV::Row objects.
3049
+ #
3050
+ # One index:
3051
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3052
+ # table = CSV.parse(source, headers: true)
3053
+ # deleted_values = table.delete(0)
3054
+ # deleted_values # => [#<CSV::Row "Name":"foo" "Value":"0">]
3055
+ #
3056
+ # Two indexes:
3057
+ # table = CSV.parse(source, headers: true)
3058
+ # deleted_values = table.delete(2, 0)
3059
+ # deleted_values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
3060
+ #
3061
+ # ---
3062
+ #
3063
+ # Returns columns data as column Arrays.
3064
+ #
3065
+ # One header:
3066
+ # table = CSV.parse(source, headers: true)
3067
+ # deleted_values = table.delete('Name')
3068
+ # deleted_values # => ["foo", "bar", "baz"]
3069
+ #
3070
+ # Two headers:
3071
+ # table = CSV.parse(source, headers: true)
3072
+ # deleted_values = table.delete('Value', 'Name')
3073
+ # deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]]
3074
+ #
3075
+ def delete: (*untyped indexes_or_headers) -> untyped
3076
+
3077
+ # <!--
3078
+ # rdoc-file=lib/csv/table.rb
3079
+ # - delete_if() { |header, self| ... }
3080
+ # -->
3081
+ # Removes rows or columns for which the block returns a truthy value; returns
3082
+ # `self`.
3083
+ #
3084
+ # Removes rows when the access mode is `:row` or `:col_or_row`; calls the block
3085
+ # with each CSV::Row object:
3086
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3087
+ # table = CSV.parse(source, headers: true)
3088
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
3089
+ # table.size # => 3
3090
+ # table.delete_if {|row| row['Name'].start_with?('b') }
3091
+ # table.size # => 1
3092
+ #
3093
+ # Removes columns when the access mode is `:col`; calls the block with each
3094
+ # column as a 2-element array containing the header and an Array of column
3095
+ # fields:
3096
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3097
+ # table = CSV.parse(source, headers: true)
3098
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
3099
+ # table.headers.size # => 2
3100
+ # table.delete_if {|column_data| column_data[1].include?('2') }
3101
+ # table.headers.size # => 1
3102
+ #
3103
+ # Returns a new Enumerator if no block is given:
3104
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3105
+ # table = CSV.parse(source, headers: true)
3106
+ # table.delete_if # => #<Enumerator: #<CSV::Table mode:col_or_row row_count:4>:delete_if>
747
3107
  #
748
3108
  def delete_if: () { (*untyped) -> untyped } -> untyped
749
3109
 
3110
+ # <!--
3111
+ # rdoc-file=lib/csv/table.rb
3112
+ # - dig(index_or_header, *index_or_headers)
3113
+ # -->
750
3114
  # Extracts the nested value specified by the sequence of `index` or `header`
751
3115
  # objects by calling dig at each step, returning nil if any intermediate step is
752
3116
  # nil.
753
3117
  #
754
3118
  def dig: (untyped index_or_header, *untyped index_or_headers) -> untyped
755
3119
 
756
- # In the default mixed mode or row mode, iteration is the standard row major
757
- # walking of rows. In column mode, iteration will `yield` two element tuples
758
- # containing the column name and an Array of values for that column.
3120
+ # <!--
3121
+ # rdoc-file=lib/csv/table.rb
3122
+ # - each() { |header, self| ... }
3123
+ # -->
3124
+ # Calls the block with each row or column; returns `self`.
759
3125
  #
760
- # This method returns the table for chaining.
3126
+ # When the access mode is `:row` or `:col_or_row`, calls the block with each
3127
+ # CSV::Row object:
3128
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3129
+ # table = CSV.parse(source, headers: true)
3130
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
3131
+ # table.each {|row| p row }
761
3132
  #
762
- # If no block is given, an Enumerator is returned.
3133
+ # Output:
3134
+ # #<CSV::Row "Name":"foo" "Value":"0">
3135
+ # #<CSV::Row "Name":"bar" "Value":"1">
3136
+ # #<CSV::Row "Name":"baz" "Value":"2">
3137
+ #
3138
+ # When the access mode is `:col`, calls the block with each column as a
3139
+ # 2-element array containing the header and an Array of column fields:
3140
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
3141
+ # table.each {|column_data| p column_data }
3142
+ #
3143
+ # Output:
3144
+ # ["Name", ["foo", "bar", "baz"]]
3145
+ # ["Value", ["0", "1", "2"]]
3146
+ #
3147
+ # Returns a new Enumerator if no block is given:
3148
+ # table.each # => #<Enumerator: #<CSV::Table mode:col row_count:4>:each>
763
3149
  #
764
3150
  def each: () -> Enumerator[untyped, self]
765
3151
  | () { (untyped) -> void } -> self
@@ -767,37 +3153,65 @@ class CSV::Table[out Elem] < Object
767
3153
 
768
3154
  def empty?: (*untyped args) { (*untyped) -> untyped } -> untyped
769
3155
 
3156
+ # <!--
3157
+ # rdoc-file=lib/csv/table.rb
3158
+ # - headers()
3159
+ # -->
770
3160
  # Returns the headers for the first row of this table (assumed to match all
771
3161
  # other rows). The headers Array passed to CSV::Table.new is returned for empty
772
3162
  # tables.
773
3163
  #
774
3164
  def headers: () -> untyped
775
3165
 
3166
+ # <!--
3167
+ # rdoc-file=lib/csv/table.rb
3168
+ # - inspect()
3169
+ # -->
776
3170
  # Shows the mode and size of this table in a US-ASCII String.
777
3171
  #
778
3172
  def inspect: () -> String
779
3173
 
780
3174
  def length: (*untyped args) { (*untyped) -> untyped } -> untyped
781
3175
 
3176
+ # <!-- rdoc-file=lib/csv/table.rb -->
782
3177
  # The current access mode for indexing and iteration.
783
3178
  #
784
3179
  def mode: () -> untyped
785
3180
 
3181
+ # <!--
3182
+ # rdoc-file=lib/csv/table.rb
3183
+ # - table.push(*rows_or_arrays) -> self
3184
+ # -->
786
3185
  # A shortcut for appending multiple rows. Equivalent to:
787
- #
788
- # rows.each { |row| self << row }
789
- #
790
- # This method returns the table for chaining.
3186
+ # rows.each {|row| self << row }
3187
+ #
3188
+ # Each argument may be either a CSV::Row object or an Array:
3189
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3190
+ # table = CSV.parse(source, headers: true)
3191
+ # rows = [
3192
+ # CSV::Row.new(table.headers, ['bat', 3]),
3193
+ # ['bam', 4]
3194
+ # ]
3195
+ # table.push(*rows)
3196
+ # table[3..4] # => [#<CSV::Row "Name":"bat" "Value":3>, #<CSV::Row "Name":"bam" "Value":4>]
791
3197
  #
792
3198
  def push: (*untyped rows) -> untyped
793
3199
 
794
3200
  def size: (*untyped args) { (*untyped) -> untyped } -> untyped
795
3201
 
3202
+ # <!--
3203
+ # rdoc-file=lib/csv/table.rb
3204
+ # - to_a()
3205
+ # -->
796
3206
  # Returns the table as an Array of Arrays. Headers will be the first row, then
797
3207
  # all of the field rows will follow.
798
3208
  #
799
3209
  def to_a: () -> untyped
800
3210
 
3211
+ # <!--
3212
+ # rdoc-file=lib/csv/table.rb
3213
+ # - to_csv(write_headers: true, **options)
3214
+ # -->
801
3215
  # Returns the table as a complete CSV String. Headers will be listed first, then
802
3216
  # all of the field rows.
803
3217
  #
@@ -806,15 +3220,65 @@ class CSV::Table[out Elem] < Object
806
3220
  #
807
3221
  def to_csv: (?write_headers: boolish, **untyped) -> untyped
808
3222
 
3223
+ # <!--
3224
+ # rdoc-file=lib/csv/table.rb
3225
+ # - to_s(write_headers: true, **options)
3226
+ # -->
3227
+ #
809
3228
  alias to_s to_csv
810
3229
 
811
- # The mixed mode default is to treat a list of indices as row access, returning
812
- # the rows indicated. Anything else is considered columnar access. For columnar
813
- # access, the return set has an Array for each row with the values indicated by
814
- # the headers in each Array. You can force column or row mode using by_col!() or
815
- # by_row!().
3230
+ # <!--
3231
+ # rdoc-file=lib/csv/table.rb
3232
+ # - table.values_at(*indexes) -> array_of_rows
3233
+ # - table.values_at(*headers) -> array_of_columns_data
3234
+ # -->
3235
+ # If the access mode is `:row` or `:col_or_row`, and each argument is either an
3236
+ # Integer or a Range, returns rows. Otherwise, returns columns data.
3237
+ #
3238
+ # In either case, the returned values are in the order specified by the
3239
+ # arguments. Arguments may be repeated.
3240
+ #
3241
+ # ---
3242
+ #
3243
+ # Returns rows as an Array of CSV::Row objects.
3244
+ #
3245
+ # No argument:
3246
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3247
+ # table = CSV.parse(source, headers: true)
3248
+ # table.values_at # => []
3249
+ #
3250
+ # One index:
3251
+ # values = table.values_at(0)
3252
+ # values # => [#<CSV::Row "Name":"foo" "Value":"0">]
3253
+ #
3254
+ # Two indexes:
3255
+ # values = table.values_at(2, 0)
3256
+ # values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
3257
+ #
3258
+ # One Range:
3259
+ # values = table.values_at(1..2)
3260
+ # values # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
3261
+ #
3262
+ # Ranges and indexes:
3263
+ # values = table.values_at(0..1, 1..2, 0, 2)
3264
+ # pp values
3265
+ #
3266
+ # Output:
3267
+ # [#<CSV::Row "Name":"foo" "Value":"0">,
3268
+ # #<CSV::Row "Name":"bar" "Value":"1">,
3269
+ # #<CSV::Row "Name":"bar" "Value":"1">,
3270
+ # #<CSV::Row "Name":"baz" "Value":"2">,
3271
+ # #<CSV::Row "Name":"foo" "Value":"0">,
3272
+ # #<CSV::Row "Name":"baz" "Value":"2">]
3273
+ #
3274
+ # ---
816
3275
  #
817
- # You cannot mix column and row access.
3276
+ # Returns columns data as row Arrays, each consisting of the specified columns
3277
+ # data for that row:
3278
+ # values = table.values_at('Name')
3279
+ # values # => [["foo"], ["bar"], ["baz"]]
3280
+ # values = table.values_at('Value', 'Name')
3281
+ # values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]]
818
3282
  #
819
3283
  def values_at: (*untyped indices_or_headers) -> untyped
820
3284
  end