xlsxrb 0.1.11 → 0.1.13

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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -34
  3. data/README.md +26 -21
  4. data/lib/xlsxrb/chart_builder.rb +18 -18
  5. data/lib/xlsxrb/dsl_helpers.rb +175 -0
  6. data/lib/xlsxrb/elements/cell.rb +56 -22
  7. data/lib/xlsxrb/elements/column.rb +27 -3
  8. data/lib/xlsxrb/elements/row.rb +27 -8
  9. data/lib/xlsxrb/elements/workbook.rb +27 -14
  10. data/lib/xlsxrb/elements/worksheet.rb +17 -1
  11. data/lib/xlsxrb/ooxml/cfb.rb +9 -6
  12. data/lib/xlsxrb/ooxml/crypto/agile.rb +5 -5
  13. data/lib/xlsxrb/ooxml/reader/listeners/core_listeners.rb +784 -0
  14. data/lib/xlsxrb/ooxml/reader/listeners/drawing_listeners.rb +3478 -0
  15. data/lib/xlsxrb/ooxml/reader/listeners/feature_listeners.rb +1796 -0
  16. data/lib/xlsxrb/ooxml/reader/listeners/style_listeners.rb +428 -0
  17. data/lib/xlsxrb/ooxml/reader/listeners.rb +4 -6446
  18. data/lib/xlsxrb/ooxml/shared_strings_parser.rb +3 -5
  19. data/lib/xlsxrb/ooxml/utils.rb +5 -6
  20. data/lib/xlsxrb/ooxml/workbook_writer.rb +5 -7
  21. data/lib/xlsxrb/ooxml/worksheet_parser.rb +172 -9
  22. data/lib/xlsxrb/ooxml/writer/drawing_xml.rb +1602 -0
  23. data/lib/xlsxrb/ooxml/writer/features_xml.rb +731 -0
  24. data/lib/xlsxrb/ooxml/writer/styles_xml.rb +348 -0
  25. data/lib/xlsxrb/ooxml/writer.rb +9 -2646
  26. data/lib/xlsxrb/ooxml/xml_builder.rb +31 -2
  27. data/lib/xlsxrb/ooxml/zip_generator.rb +26 -5
  28. data/lib/xlsxrb/ooxml/zip_reader.rb +364 -78
  29. data/lib/xlsxrb/ooxml/zip_writer.rb +32 -5
  30. data/lib/xlsxrb/stream_sheet.rb +94 -6
  31. data/lib/xlsxrb/stream_writer.rb +48 -115
  32. data/lib/xlsxrb/style_builder.rb +10 -1
  33. data/lib/xlsxrb/version.rb +1 -1
  34. data/lib/xlsxrb/workbook_builder.rb +1 -1
  35. data/lib/xlsxrb/worksheet_builder.rb +19 -81
  36. data/lib/xlsxrb.rb +449 -171
  37. data/sig/generated/xlsxrb/chart_builder.rbs +36 -36
  38. data/sig/generated/xlsxrb/dsl_helpers.rbs +92 -0
  39. data/sig/generated/xlsxrb/elements/cell.rbs +29 -0
  40. data/sig/generated/xlsxrb/elements/column.rbs +32 -21
  41. data/sig/generated/xlsxrb/elements/row.rbs +94 -14
  42. data/sig/generated/xlsxrb/elements/workbook.rbs +102 -10
  43. data/sig/generated/xlsxrb/elements/worksheet.rbs +9 -0
  44. data/sig/generated/xlsxrb/ooxml/reader/listeners/core_listeners.rbs +173 -0
  45. data/sig/generated/xlsxrb/ooxml/reader/listeners/drawing_listeners.rbs +400 -0
  46. data/sig/generated/xlsxrb/ooxml/reader/listeners/feature_listeners.rbs +442 -0
  47. data/sig/generated/xlsxrb/ooxml/reader/listeners/style_listeners.rbs +80 -0
  48. data/sig/generated/xlsxrb/ooxml/reader/listeners.rbs +0 -1072
  49. data/sig/generated/xlsxrb/ooxml/shared_strings_parser.rbs +0 -2
  50. data/sig/generated/xlsxrb/ooxml/utils.rbs +2 -0
  51. data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +5 -4
  52. data/sig/generated/xlsxrb/ooxml/writer/drawing_xml.rbs +79 -0
  53. data/sig/generated/xlsxrb/ooxml/writer/features_xml.rbs +83 -0
  54. data/sig/generated/xlsxrb/ooxml/writer/styles_xml.rbs +53 -0
  55. data/sig/generated/xlsxrb/ooxml/writer.rbs +6 -185
  56. data/sig/generated/xlsxrb/ooxml/xml_builder.rbs +18 -0
  57. data/sig/generated/xlsxrb/ooxml/zip_generator.rbs +15 -0
  58. data/sig/generated/xlsxrb/ooxml/zip_reader.rbs +96 -8
  59. data/sig/generated/xlsxrb/ooxml/zip_writer.rbs +5 -1
  60. data/sig/generated/xlsxrb/stream_sheet.rbs +43 -3
  61. data/sig/generated/xlsxrb/style_builder.rbs +7 -0
  62. data/sig/generated/xlsxrb.rbs +18 -11
  63. metadata +22 -144
  64. data/.devcontainer/Dockerfile +0 -65
  65. data/.devcontainer/devcontainer.json +0 -17
  66. data/.gem_rbs_collection/ast/2.4/.rbs_meta.yaml +0 -9
  67. data/.gem_rbs_collection/ast/2.4/ast.rbs +0 -73
  68. data/.gem_rbs_collection/concurrent-ruby/1.1/.rbs_meta.yaml +0 -9
  69. data/.gem_rbs_collection/concurrent-ruby/1.1/array.rbs +0 -4
  70. data/.gem_rbs_collection/concurrent-ruby/1.1/atomic_reference.rbs +0 -16
  71. data/.gem_rbs_collection/concurrent-ruby/1.1/executor.rbs +0 -96
  72. data/.gem_rbs_collection/concurrent-ruby/1.1/hash.rbs +0 -4
  73. data/.gem_rbs_collection/concurrent-ruby/1.1/map.rbs +0 -68
  74. data/.gem_rbs_collection/concurrent-ruby/1.1/promises.rbs +0 -249
  75. data/.gem_rbs_collection/concurrent-ruby/1.1/set.rbs +0 -4
  76. data/.gem_rbs_collection/concurrent-ruby/1.1/timer_task.rbs +0 -47
  77. data/.gem_rbs_collection/concurrent-ruby/1.1/utility/processor_counter.rbs +0 -5
  78. data/.gem_rbs_collection/csv/3.3/.rbs_meta.yaml +0 -9
  79. data/.gem_rbs_collection/csv/3.3/csv.rbs +0 -3871
  80. data/.gem_rbs_collection/csv/3.3/manifest.yaml +0 -3
  81. data/.gem_rbs_collection/lint_roller/1.1/.rbs_meta.yaml +0 -9
  82. data/.gem_rbs_collection/lint_roller/1.1/lint_roller.rbs +0 -48
  83. data/.gem_rbs_collection/listen/3.9/.rbs_meta.yaml +0 -9
  84. data/.gem_rbs_collection/listen/3.9/listen.rbs +0 -25
  85. data/.gem_rbs_collection/listen/3.9/listener.rbs +0 -24
  86. data/.gem_rbs_collection/logger/1.7/.rbs_meta.yaml +0 -9
  87. data/.gem_rbs_collection/logger/1.7/formatter.rbs +0 -45
  88. data/.gem_rbs_collection/logger/1.7/log_device.rbs +0 -100
  89. data/.gem_rbs_collection/logger/1.7/logger.rbs +0 -796
  90. data/.gem_rbs_collection/logger/1.7/manifest.yaml +0 -2
  91. data/.gem_rbs_collection/logger/1.7/period.rbs +0 -17
  92. data/.gem_rbs_collection/logger/1.7/severity.rbs +0 -34
  93. data/.gem_rbs_collection/nokogiri/1.11/.rbs_meta.yaml +0 -9
  94. data/.gem_rbs_collection/nokogiri/1.11/nokogiri.rbs +0 -2332
  95. data/.gem_rbs_collection/nokogiri/1.11/patch.rbs +0 -4
  96. data/.gem_rbs_collection/parallel/1.20/.rbs_meta.yaml +0 -9
  97. data/.gem_rbs_collection/parallel/1.20/parallel.rbs +0 -86
  98. data/.gem_rbs_collection/parser/3.2/.rbs_meta.yaml +0 -9
  99. data/.gem_rbs_collection/parser/3.2/manifest.yaml +0 -7
  100. data/.gem_rbs_collection/parser/3.2/parser.rbs +0 -194
  101. data/.gem_rbs_collection/parser/3.2/polyfill.rbs +0 -4
  102. data/.gem_rbs_collection/rainbow/3.0/.rbs_meta.yaml +0 -9
  103. data/.gem_rbs_collection/rainbow/3.0/global.rbs +0 -7
  104. data/.gem_rbs_collection/rainbow/3.0/presenter.rbs +0 -209
  105. data/.gem_rbs_collection/rainbow/3.0/rainbow.rbs +0 -5
  106. data/.gem_rbs_collection/rake/13.0/.rbs_meta.yaml +0 -9
  107. data/.gem_rbs_collection/rake/13.0/manifest.yaml +0 -2
  108. data/.gem_rbs_collection/rake/13.0/rake.rbs +0 -39
  109. data/.gem_rbs_collection/regexp_parser/2.8/.rbs_meta.yaml +0 -9
  110. data/.gem_rbs_collection/regexp_parser/2.8/regexp_parser.rbs +0 -17
  111. data/.gem_rbs_collection/rubocop/1.57/.rbs_meta.yaml +0 -9
  112. data/.gem_rbs_collection/rubocop/1.57/rubocop.rbs +0 -208
  113. data/.gem_rbs_collection/rubocop-ast/1.46/.rbs_meta.yaml +0 -9
  114. data/.gem_rbs_collection/rubocop-ast/1.46/rubocop-ast.rbs +0 -903
  115. data/.gem_rbs_collection/rubyzip/3.2/.rbs_meta.yaml +0 -9
  116. data/.gem_rbs_collection/rubyzip/3.2/manifest.yaml +0 -8
  117. data/.gem_rbs_collection/rubyzip/3.2/zip/central_directory.rbs +0 -42
  118. data/.gem_rbs_collection/rubyzip/3.2/zip/compressor.rbs +0 -5
  119. data/.gem_rbs_collection/rubyzip/3.2/zip/constants.rbs +0 -47
  120. data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/aes_encryption.rbs +0 -30
  121. data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/decrypted_io.rbs +0 -9
  122. data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/encryption.rbs +0 -7
  123. data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/null_encryption.rbs +0 -19
  124. data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/traditional_encryption.rbs +0 -31
  125. data/.gem_rbs_collection/rubyzip/3.2/zip/decompressor.rbs +0 -18
  126. data/.gem_rbs_collection/rubyzip/3.2/zip/deflater.rbs +0 -12
  127. data/.gem_rbs_collection/rubyzip/3.2/zip/dirtyable.rbs +0 -11
  128. data/.gem_rbs_collection/rubyzip/3.2/zip/dos_time.rbs +0 -13
  129. data/.gem_rbs_collection/rubyzip/3.2/zip/entry.rbs +0 -95
  130. data/.gem_rbs_collection/rubyzip/3.2/zip/entry_set.rbs +0 -31
  131. data/.gem_rbs_collection/rubyzip/3.2/zip/errors.rbs +0 -58
  132. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/aes.rbs +0 -24
  133. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/generic.rbs +0 -17
  134. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/ntfs.rbs +0 -23
  135. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/old_unix.rbs +0 -22
  136. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/universal_time.rbs +0 -30
  137. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/unix.rbs +0 -20
  138. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/unknown.rbs +0 -15
  139. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/zip64.rbs +0 -26
  140. data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field.rbs +0 -21
  141. data/.gem_rbs_collection/rubyzip/3.2/zip/file.rbs +0 -131
  142. data/.gem_rbs_collection/rubyzip/3.2/zip/file_split.rbs +0 -14
  143. data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/dir.rbs +0 -33
  144. data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/directory_iterator.rbs +0 -21
  145. data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/file.rbs +0 -63
  146. data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/file_stat.rbs +0 -55
  147. data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/zip_file_name_mapper.rbs +0 -35
  148. data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem.rbs +0 -7
  149. data/.gem_rbs_collection/rubyzip/3.2/zip/inflater.rbs +0 -10
  150. data/.gem_rbs_collection/rubyzip/3.2/zip/input_stream.rbs +0 -22
  151. data/.gem_rbs_collection/rubyzip/3.2/zip/ioextras/abstract_input_stream.rbs +0 -29
  152. data/.gem_rbs_collection/rubyzip/3.2/zip/ioextras/abstract_output_stream.rbs +0 -17
  153. data/.gem_rbs_collection/rubyzip/3.2/zip/ioextras.rbs +0 -13
  154. data/.gem_rbs_collection/rubyzip/3.2/zip/null_compressor.rbs +0 -10
  155. data/.gem_rbs_collection/rubyzip/3.2/zip/null_decompressor.rbs +0 -8
  156. data/.gem_rbs_collection/rubyzip/3.2/zip/null_input_stream.rbs +0 -6
  157. data/.gem_rbs_collection/rubyzip/3.2/zip/output_stream.rbs +0 -30
  158. data/.gem_rbs_collection/rubyzip/3.2/zip/pass_thru_compressor.rbs +0 -10
  159. data/.gem_rbs_collection/rubyzip/3.2/zip/pass_thru_decompressor.rbs +0 -10
  160. data/.gem_rbs_collection/rubyzip/3.2/zip/streamable_directory.rbs +0 -5
  161. data/.gem_rbs_collection/rubyzip/3.2/zip/streamable_stream.rbs +0 -15
  162. data/.gem_rbs_collection/rubyzip/3.2/zip/version.rbs +0 -3
  163. data/.gem_rbs_collection/rubyzip/3.2/zip.rbs +0 -40
  164. data/Rakefile +0 -567
  165. data/Steepfile +0 -18
  166. data/benchmark.rb +0 -406
  167. data/docs/ARCHITECTURE.md +0 -514
  168. data/docs/DEVELOPMENT.md +0 -133
  169. data/docs/PEER_LIBRARIES.md +0 -121
  170. data/docs/QUALITY_ASSURANCE.md +0 -25
  171. data/docs/SPEC_SOURCES.md +0 -48
  172. data/docs/assets/benchmark_results.svg +0 -144
  173. data/docs/assets/lsp_autocompletion.png +0 -0
  174. data/docs/assets/playground_preview.png +0 -0
  175. data/docs/coi-serviceworker.js +0 -82
  176. data/docs/office_thread.js +0 -77
  177. data/docs/preview.html +0 -719
  178. data/docs/visual/VisualGallery.md +0 -4672
  179. data/docs/wasm/ruby.wasm +0 -0
  180. data/docs/wasm/wasm_doc_helper.css +0 -351
  181. data/docs/wasm/wasm_doc_helper.js +0 -439
  182. data/docs/zeta.js +0 -1107
  183. data/rbs_collection.lock.yaml +0 -252
  184. data/rbs_collection.yaml +0 -19
  185. data/vendor/sdk_runner/Program.cs +0 -93
  186. data/vendor/sdk_runner/sdk_runner.csproj +0 -13
@@ -1,3871 +0,0 @@
1
- # <!-- rdoc-file=lib/csv.rb -->
2
- # ## CSV
3
- #
4
- # ### CSV Data
5
- #
6
- # CSV (comma-separated values) data is a text representation of a table:
7
- # * A *row* *separator* delimits table rows. A common row separator is the
8
- # newline character `"\n"`.
9
- # * A *column* *separator* delimits fields in a row. A common column separator
10
- # is the comma character `","`.
11
- #
12
- # This CSV String, with row separator `"\n"` and column separator `","`, has
13
- # three rows and two columns:
14
- # "foo,0\nbar,1\nbaz,2\n"
15
- #
16
- # Despite the name CSV, a CSV representation can use different separators.
17
- #
18
- # For more about tables, see the Wikipedia article "[Table
19
- # (information)](https://en.wikipedia.org/wiki/Table_(information))", especially
20
- # its section "[Simple
21
- # table](https://en.wikipedia.org/wiki/Table_(information)#Simple_table)"
22
- #
23
- # ## Class CSV
24
- #
25
- # Class CSV provides methods for:
26
- # * Parsing CSV data from a String object, a File (via its file path), or an
27
- # IO object.
28
- # * Generating CSV data to a String object.
29
- #
30
- # To make CSV available:
31
- # require 'csv'
32
- #
33
- # All examples here assume that this has been done.
34
- #
35
- # ## Keeping It Simple
36
- #
37
- # A CSV object has dozens of instance methods that offer fine-grained control of
38
- # parsing and generating CSV data. For many needs, though, simpler approaches
39
- # will do.
40
- #
41
- # This section summarizes the singleton methods in CSV that allow you to parse
42
- # and generate without explicitly creating CSV objects. For details, follow the
43
- # links.
44
- #
45
- # ### Simple Parsing
46
- #
47
- # Parsing methods commonly return either of:
48
- # * An Array of Arrays of Strings:
49
- # * The outer Array is the entire "table".
50
- # * Each inner Array is a row.
51
- # * Each String is a field.
52
- # * A CSV::Table object. For details, see [\CSV with
53
- # Headers](#class-CSV-label-CSV+with+Headers).
54
- #
55
- # #### Parsing a String
56
- #
57
- # The input to be parsed can be a string:
58
- # string = "foo,0\nbar,1\nbaz,2\n"
59
- #
60
- # Method CSV.parse returns the entire CSV data:
61
- # CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
62
- #
63
- # Method CSV.parse_line returns only the first row:
64
- # CSV.parse_line(string) # => ["foo", "0"]
65
- #
66
- # CSV extends class String with instance method String#parse_csv, which also
67
- # returns only the first row:
68
- # string.parse_csv # => ["foo", "0"]
69
- #
70
- # #### Parsing Via a File Path
71
- #
72
- # The input to be parsed can be in a file:
73
- # string = "foo,0\nbar,1\nbaz,2\n"
74
- # path = 't.csv'
75
- # File.write(path, string)
76
- #
77
- # Method CSV.read returns the entire CSV data:
78
- # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
79
- #
80
- # Method CSV.foreach iterates, passing each row to the given block:
81
- # CSV.foreach(path) do |row|
82
- # p row
83
- # end
84
- #
85
- # Output:
86
- # ["foo", "0"]
87
- # ["bar", "1"]
88
- # ["baz", "2"]
89
- #
90
- # Method CSV.table returns the entire CSV data as a CSV::Table object:
91
- # CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:3>
92
- #
93
- # #### Parsing from an Open IO Stream
94
- #
95
- # The input to be parsed can be in an open IO stream:
96
- #
97
- # Method CSV.read returns the entire CSV data:
98
- # File.open(path) do |file|
99
- # CSV.read(file)
100
- # end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
101
- #
102
- # As does method CSV.parse:
103
- # File.open(path) do |file|
104
- # CSV.parse(file)
105
- # end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
106
- #
107
- # Method CSV.parse_line returns only the first row:
108
- # File.open(path) do |file|
109
- # CSV.parse_line(file)
110
- # end # => ["foo", "0"]
111
- #
112
- # Method CSV.foreach iterates, passing each row to the given block:
113
- # File.open(path) do |file|
114
- # CSV.foreach(file) do |row|
115
- # p row
116
- # end
117
- # end
118
- #
119
- # Output:
120
- # ["foo", "0"]
121
- # ["bar", "1"]
122
- # ["baz", "2"]
123
- #
124
- # Method CSV.table returns the entire CSV data as a CSV::Table object:
125
- # File.open(path) do |file|
126
- # CSV.table(file)
127
- # end # => #<CSV::Table mode:col_or_row row_count:3>
128
- #
129
- # ### Simple Generating
130
- #
131
- # Method CSV.generate returns a String; this example uses method CSV#<< to
132
- # append the rows that are to be generated:
133
- # output_string = CSV.generate do |csv|
134
- # csv << ['foo', 0]
135
- # csv << ['bar', 1]
136
- # csv << ['baz', 2]
137
- # end
138
- # output_string # => "foo,0\nbar,1\nbaz,2\n"
139
- #
140
- # Method CSV.generate_line returns a String containing the single row
141
- # constructed from an Array:
142
- # CSV.generate_line(['foo', '0']) # => "foo,0\n"
143
- #
144
- # CSV extends class Array with instance method `Array#to_csv`, which forms an
145
- # Array into a String:
146
- # ['foo', '0'].to_csv # => "foo,0\n"
147
- #
148
- # ### "Filtering" CSV
149
- #
150
- # Method CSV.filter provides a Unix-style filter for CSV data. The input data is
151
- # processed to form the output data:
152
- # in_string = "foo,0\nbar,1\nbaz,2\n"
153
- # out_string = ''
154
- # CSV.filter(in_string, out_string) do |row|
155
- # row[0] = row[0].upcase
156
- # row[1] *= 4
157
- # end
158
- # out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
159
- #
160
- # ## CSV Objects
161
- #
162
- # There are three ways to create a CSV object:
163
- # * Method CSV.new returns a new CSV object.
164
- # * Method CSV.instance returns a new or cached CSV object.
165
- # * Method CSV() also returns a new or cached CSV object.
166
- #
167
- # ### Instance Methods
168
- #
169
- # CSV has three groups of instance methods:
170
- # * Its own internally defined instance methods.
171
- # * Methods included by module Enumerable.
172
- # * Methods delegated to class IO. See below.
173
- #
174
- # #### Delegated Methods
175
- #
176
- # For convenience, a CSV object will delegate to many methods in class IO. (A
177
- # few have wrapper "guard code" in CSV.) You may call:
178
- # * IO#binmode
179
- # * #binmode?
180
- # * IO#close
181
- # * IO#close_read
182
- # * IO#close_write
183
- # * IO#closed?
184
- # * #eof
185
- # * #eof?
186
- # * IO#external_encoding
187
- # * IO#fcntl
188
- # * IO#fileno
189
- # * #flock
190
- # * IO#flush
191
- # * IO#fsync
192
- # * IO#internal_encoding
193
- # * #ioctl
194
- # * IO#isatty
195
- # * #path
196
- # * IO#pid
197
- # * IO#pos
198
- # * IO#pos=
199
- # * IO#reopen
200
- # * #rewind
201
- # * IO#seek
202
- # * #stat
203
- # * IO#string
204
- # * IO#sync
205
- # * IO#sync=
206
- # * IO#tell
207
- # * #to_i
208
- # * #to_io
209
- # * IO#truncate
210
- # * IO#tty?
211
- #
212
- # ### Options
213
- #
214
- # The default values for options are:
215
- # DEFAULT_OPTIONS = {
216
- # # For both parsing and generating.
217
- # col_sep: ",",
218
- # row_sep: :auto,
219
- # quote_char: '"',
220
- # # For parsing.
221
- # field_size_limit: nil,
222
- # converters: nil,
223
- # unconverted_fields: nil,
224
- # headers: false,
225
- # return_headers: false,
226
- # header_converters: nil,
227
- # skip_blanks: false,
228
- # skip_lines: nil,
229
- # liberal_parsing: false,
230
- # nil_value: nil,
231
- # empty_value: "",
232
- # strip: false,
233
- # # For generating.
234
- # write_headers: nil,
235
- # quote_empty: true,
236
- # force_quotes: false,
237
- # write_converters: nil,
238
- # write_nil_value: nil,
239
- # write_empty_value: "",
240
- # }
241
- #
242
- # #### Options for Parsing
243
- #
244
- # Options for parsing, described in detail below, include:
245
- # * `row_sep`: Specifies the row separator; used to delimit rows.
246
- # * `col_sep`: Specifies the column separator; used to delimit fields.
247
- # * `quote_char`: Specifies the quote character; used to quote fields.
248
- # * `field_size_limit`: Specifies the maximum field size + 1 allowed.
249
- # Deprecated since 3.2.3. Use `max_field_size` instead.
250
- # * `max_field_size`: Specifies the maximum field size allowed.
251
- # * `converters`: Specifies the field converters to be used.
252
- # * `unconverted_fields`: Specifies whether unconverted fields are to be
253
- # available.
254
- # * `headers`: Specifies whether data contains headers, or specifies the
255
- # headers themselves.
256
- # * `return_headers`: Specifies whether headers are to be returned.
257
- # * `header_converters`: Specifies the header converters to be used.
258
- # * `skip_blanks`: Specifies whether blanks lines are to be ignored.
259
- # * `skip_lines`: Specifies how comments lines are to be recognized.
260
- # * `strip`: Specifies whether leading and trailing whitespace are to be
261
- # stripped from fields. This must be compatible with `col_sep`; if it is
262
- # not, then an `ArgumentError` exception will be raised.
263
- # * `liberal_parsing`: Specifies whether CSV should attempt to parse
264
- # non-compliant data.
265
- # * `nil_value`: Specifies the object that is to be substituted for each null
266
- # (no-text) field.
267
- # * `empty_value`: Specifies the object that is to be substituted for each
268
- # empty field.
269
- #
270
- # ###### Option `row_sep`
271
- #
272
- # Specifies the row separator, a String or the Symbol `:auto` (see below), to be
273
- # used for both parsing and generating.
274
- #
275
- # Default value:
276
- # CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto
277
- #
278
- # ---
279
- #
280
- # When `row_sep` is a String, that String becomes the row separator. The String
281
- # will be transcoded into the data's Encoding before use.
282
- #
283
- # Using `"\n"`:
284
- # row_sep = "\n"
285
- # str = CSV.generate(row_sep: row_sep) do |csv|
286
- # csv << [:foo, 0]
287
- # csv << [:bar, 1]
288
- # csv << [:baz, 2]
289
- # end
290
- # str # => "foo,0\nbar,1\nbaz,2\n"
291
- # ary = CSV.parse(str)
292
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
293
- #
294
- # Using `|` (pipe):
295
- # row_sep = '|'
296
- # str = CSV.generate(row_sep: row_sep) do |csv|
297
- # csv << [:foo, 0]
298
- # csv << [:bar, 1]
299
- # csv << [:baz, 2]
300
- # end
301
- # str # => "foo,0|bar,1|baz,2|"
302
- # ary = CSV.parse(str, row_sep: row_sep)
303
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
304
- #
305
- # Using `--` (two hyphens):
306
- # row_sep = '--'
307
- # str = CSV.generate(row_sep: row_sep) do |csv|
308
- # csv << [:foo, 0]
309
- # csv << [:bar, 1]
310
- # csv << [:baz, 2]
311
- # end
312
- # str # => "foo,0--bar,1--baz,2--"
313
- # ary = CSV.parse(str, row_sep: row_sep)
314
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
315
- #
316
- # Using `''` (empty string):
317
- # row_sep = ''
318
- # str = CSV.generate(row_sep: row_sep) do |csv|
319
- # csv << [:foo, 0]
320
- # csv << [:bar, 1]
321
- # csv << [:baz, 2]
322
- # end
323
- # str # => "foo,0bar,1baz,2"
324
- # ary = CSV.parse(str, row_sep: row_sep)
325
- # ary # => [["foo", "0bar", "1baz", "2"]]
326
- #
327
- # ---
328
- #
329
- # When `row_sep` is the Symbol `:auto` (the default), generating uses `"\n"` as
330
- # the row separator:
331
- # str = CSV.generate do |csv|
332
- # csv << [:foo, 0]
333
- # csv << [:bar, 1]
334
- # csv << [:baz, 2]
335
- # end
336
- # str # => "foo,0\nbar,1\nbaz,2\n"
337
- #
338
- # Parsing, on the other hand, invokes auto-discovery of the row separator.
339
- #
340
- # Auto-discovery reads ahead in the data looking for the next `\r\n`, `\n`, or
341
- # `\r` sequence. The sequence will be selected even if it occurs in a quoted
342
- # field, assuming that you would have the same line endings there.
343
- #
344
- # Example:
345
- # str = CSV.generate do |csv|
346
- # csv << [:foo, 0]
347
- # csv << [:bar, 1]
348
- # csv << [:baz, 2]
349
- # end
350
- # str # => "foo,0\nbar,1\nbaz,2\n"
351
- # ary = CSV.parse(str)
352
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
353
- #
354
- # The default `$INPUT_RECORD_SEPARATOR` (`$/`) is used if any of the following
355
- # is true:
356
- # * None of those sequences is found.
357
- # * Data is `ARGF`, `STDIN`, `STDOUT`, or `STDERR`.
358
- # * The stream is only available for output.
359
- #
360
- # Obviously, discovery takes a little time. Set manually if speed is important.
361
- # Also note that IO objects should be opened in binary mode on Windows if this
362
- # feature will be used as the line-ending translation can cause problems with
363
- # resetting the document position to where it was before the read ahead.
364
- #
365
- # ###### Option `col_sep`
366
- #
367
- # Specifies the String field separator to be used for both parsing and
368
- # generating. The String will be transcoded into the data's Encoding before use.
369
- #
370
- # Default value:
371
- # CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma)
372
- #
373
- # Using the default (comma):
374
- # str = CSV.generate do |csv|
375
- # csv << [:foo, 0]
376
- # csv << [:bar, 1]
377
- # csv << [:baz, 2]
378
- # end
379
- # str # => "foo,0\nbar,1\nbaz,2\n"
380
- # ary = CSV.parse(str)
381
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
382
- #
383
- # Using `:` (colon):
384
- # col_sep = ':'
385
- # str = CSV.generate(col_sep: col_sep) do |csv|
386
- # csv << [:foo, 0]
387
- # csv << [:bar, 1]
388
- # csv << [:baz, 2]
389
- # end
390
- # str # => "foo:0\nbar:1\nbaz:2\n"
391
- # ary = CSV.parse(str, col_sep: col_sep)
392
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
393
- #
394
- # Using `::` (two colons):
395
- # col_sep = '::'
396
- # str = CSV.generate(col_sep: col_sep) do |csv|
397
- # csv << [:foo, 0]
398
- # csv << [:bar, 1]
399
- # csv << [:baz, 2]
400
- # end
401
- # str # => "foo::0\nbar::1\nbaz::2\n"
402
- # ary = CSV.parse(str, col_sep: col_sep)
403
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
404
- #
405
- # Using `''` (empty string):
406
- # col_sep = ''
407
- # str = CSV.generate(col_sep: col_sep) do |csv|
408
- # csv << [:foo, 0]
409
- # csv << [:bar, 1]
410
- # csv << [:baz, 2]
411
- # end
412
- # str # => "foo0\nbar1\nbaz2\n"
413
- #
414
- # ---
415
- #
416
- # Raises an exception if parsing with the empty String:
417
- # col_sep = ''
418
- # # Raises ArgumentError (:col_sep must be 1 or more characters: "")
419
- # CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep)
420
- #
421
- # ###### Option `quote_char`
422
- #
423
- # Specifies the character (String of length 1) used used to quote fields in both
424
- # parsing and generating. This String will be transcoded into the data's
425
- # Encoding before use.
426
- #
427
- # Default value:
428
- # CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote)
429
- #
430
- # This is useful for an application that incorrectly uses `'` (single-quote) to
431
- # quote fields, instead of the correct `"` (double-quote).
432
- #
433
- # Using the default (double quote):
434
- # str = CSV.generate do |csv|
435
- # csv << ['foo', 0]
436
- # csv << ["'bar'", 1]
437
- # csv << ['"baz"', 2]
438
- # end
439
- # str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n"
440
- # ary = CSV.parse(str)
441
- # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
442
- #
443
- # Using `'` (single-quote):
444
- # quote_char = "'"
445
- # str = CSV.generate(quote_char: quote_char) do |csv|
446
- # csv << ['foo', 0]
447
- # csv << ["'bar'", 1]
448
- # csv << ['"baz"', 2]
449
- # end
450
- # str # => "foo,0\n'''bar''',1\n\"baz\",2\n"
451
- # ary = CSV.parse(str, quote_char: quote_char)
452
- # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
453
- #
454
- # ---
455
- #
456
- # Raises an exception if the String length is greater than 1:
457
- # # Raises ArgumentError (:quote_char has to be nil or a single character String)
458
- # CSV.new('', quote_char: 'xx')
459
- #
460
- # Raises an exception if the value is not a String:
461
- # # Raises ArgumentError (:quote_char has to be nil or a single character String)
462
- # CSV.new('', quote_char: :foo)
463
- #
464
- # ###### Option `field_size_limit`
465
- #
466
- # Specifies the Integer field size limit.
467
- #
468
- # Default value:
469
- # CSV::DEFAULT_OPTIONS.fetch(:field_size_limit) # => nil
470
- #
471
- # This is a maximum size CSV will read ahead looking for the closing quote for a
472
- # field. (In truth, it reads to the first line ending beyond this size.) If a
473
- # quote cannot be found within the limit CSV will raise a MalformedCSVError,
474
- # assuming the data is faulty. You can use this limit to prevent what are
475
- # effectively DoS attacks on the parser. However, this limit can cause a
476
- # legitimate parse to fail; therefore the default value is `nil` (no limit).
477
- #
478
- # For the examples in this section:
479
- # str = <<~EOT
480
- # "a","b"
481
- # "
482
- # 2345
483
- # ",""
484
- # EOT
485
- # str # => "\"a\",\"b\"\n\"\n2345\n\",\"\"\n"
486
- #
487
- # Using the default `nil`:
488
- # ary = CSV.parse(str)
489
- # ary # => [["a", "b"], ["\n2345\n", ""]]
490
- #
491
- # Using `50`:
492
- # field_size_limit = 50
493
- # ary = CSV.parse(str, field_size_limit: field_size_limit)
494
- # ary # => [["a", "b"], ["\n2345\n", ""]]
495
- #
496
- # ---
497
- #
498
- # Raises an exception if a field is too long:
499
- # big_str = "123456789\n" * 1024
500
- # # Raises CSV::MalformedCSVError (Field size exceeded in line 1.)
501
- # CSV.parse('valid,fields,"' + big_str + '"', field_size_limit: 2048)
502
- #
503
- # ###### Option `converters`
504
- #
505
- # Specifies converters to be used in parsing fields. See [Field
506
- # Converters](#class-CSV-label-Field+Converters)
507
- #
508
- # Default value:
509
- # CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil
510
- #
511
- # The value may be a field converter name (see [Stored
512
- # Converters](#class-CSV-label-Stored+Converters)):
513
- # str = '1,2,3'
514
- # # Without a converter
515
- # array = CSV.parse_line(str)
516
- # array # => ["1", "2", "3"]
517
- # # With built-in converter :integer
518
- # array = CSV.parse_line(str, converters: :integer)
519
- # array # => [1, 2, 3]
520
- #
521
- # The value may be a converter list (see [Converter
522
- # Lists](#class-CSV-label-Converter+Lists)):
523
- # str = '1,3.14159'
524
- # # Without converters
525
- # array = CSV.parse_line(str)
526
- # array # => ["1", "3.14159"]
527
- # # With built-in converters
528
- # array = CSV.parse_line(str, converters: [:integer, :float])
529
- # array # => [1, 3.14159]
530
- #
531
- # The value may be a Proc custom converter: (see [Custom Field
532
- # Converters](#class-CSV-label-Custom+Field+Converters)):
533
- # str = ' foo , bar , baz '
534
- # # Without a converter
535
- # array = CSV.parse_line(str)
536
- # array # => [" foo ", " bar ", " baz "]
537
- # # With a custom converter
538
- # array = CSV.parse_line(str, converters: proc {|field| field.strip })
539
- # array # => ["foo", "bar", "baz"]
540
- #
541
- # See also [Custom Field Converters](#class-CSV-label-Custom+Field+Converters)
542
- #
543
- # ---
544
- #
545
- # Raises an exception if the converter is not a converter name or a Proc:
546
- # str = 'foo,0'
547
- # # Raises NoMethodError (undefined method `arity' for nil:NilClass)
548
- # CSV.parse(str, converters: :foo)
549
- #
550
- # ###### Option `unconverted_fields`
551
- #
552
- # Specifies the boolean that determines whether unconverted field values are to
553
- # be available.
554
- #
555
- # Default value:
556
- # CSV::DEFAULT_OPTIONS.fetch(:unconverted_fields) # => nil
557
- #
558
- # The unconverted field values are those found in the source data, prior to any
559
- # conversions performed via option `converters`.
560
- #
561
- # When option `unconverted_fields` is `true`, each returned row (Array or
562
- # CSV::Row) has an added method, `unconverted_fields`, that returns the
563
- # unconverted field values:
564
- # str = <<-EOT
565
- # foo,0
566
- # bar,1
567
- # baz,2
568
- # EOT
569
- # # Without unconverted_fields
570
- # csv = CSV.parse(str, converters: :integer)
571
- # csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
572
- # csv.first.respond_to?(:unconverted_fields) # => false
573
- # # With unconverted_fields
574
- # csv = CSV.parse(str, converters: :integer, unconverted_fields: true)
575
- # csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
576
- # csv.first.respond_to?(:unconverted_fields) # => true
577
- # csv.first.unconverted_fields # => ["foo", "0"]
578
- #
579
- # ###### Option `headers`
580
- #
581
- # Specifies a boolean, Symbol, Array, or String to be used to define column
582
- # headers.
583
- #
584
- # Default value:
585
- # CSV::DEFAULT_OPTIONS.fetch(:headers) # => false
586
- #
587
- # ---
588
- #
589
- # Without `headers`:
590
- # str = <<-EOT
591
- # Name,Count
592
- # foo,0
593
- # bar,1
594
- # bax,2
595
- # EOT
596
- # csv = CSV.new(str)
597
- # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
598
- # csv.headers # => nil
599
- # csv.shift # => ["Name", "Count"]
600
- #
601
- # ---
602
- #
603
- # If set to `true` or the Symbol `:first_row`, the first row of the data is
604
- # treated as a row of headers:
605
- # str = <<-EOT
606
- # Name,Count
607
- # foo,0
608
- # bar,1
609
- # bax,2
610
- # EOT
611
- # csv = CSV.new(str, headers: true)
612
- # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["Name", "Count"]>
613
- # csv.headers # => ["Name", "Count"]
614
- # csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
615
- #
616
- # ---
617
- #
618
- # If set to an Array, the Array elements are treated as headers:
619
- # str = <<-EOT
620
- # foo,0
621
- # bar,1
622
- # bax,2
623
- # EOT
624
- # csv = CSV.new(str, headers: ['Name', 'Count'])
625
- # csv
626
- # csv.headers # => ["Name", "Count"]
627
- # csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
628
- #
629
- # ---
630
- #
631
- # If set to a String `str`, method `CSV::parse_line(str, options)` is called
632
- # with the current `options`, and the returned Array is treated as headers:
633
- # str = <<-EOT
634
- # foo,0
635
- # bar,1
636
- # bax,2
637
- # EOT
638
- # csv = CSV.new(str, headers: 'Name,Count')
639
- # csv
640
- # csv.headers # => ["Name", "Count"]
641
- # csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
642
- #
643
- # ###### Option `return_headers`
644
- #
645
- # Specifies the boolean that determines whether method #shift returns or ignores
646
- # the header row.
647
- #
648
- # Default value:
649
- # CSV::DEFAULT_OPTIONS.fetch(:return_headers) # => false
650
- #
651
- # Examples:
652
- # str = <<-EOT
653
- # Name,Count
654
- # foo,0
655
- # bar,1
656
- # bax,2
657
- # EOT
658
- # # Without return_headers first row is str.
659
- # csv = CSV.new(str, headers: true)
660
- # csv.shift # => #<CSV::Row "Name":"foo" "Count":"0">
661
- # # With return_headers first row is headers.
662
- # csv = CSV.new(str, headers: true, return_headers: true)
663
- # csv.shift # => #<CSV::Row "Name":"Name" "Count":"Count">
664
- #
665
- # ###### Option `header_converters`
666
- #
667
- # Specifies converters to be used in parsing headers. See [Header
668
- # Converters](#class-CSV-label-Header+Converters)
669
- #
670
- # Default value:
671
- # CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil
672
- #
673
- # Identical in functionality to option
674
- # [converters](#class-CSV-label-Option+converters) except that:
675
- # * The converters apply only to the header row.
676
- # * The built-in header converters are `:downcase` and `:symbol`.
677
- #
678
- # This section assumes prior execution of:
679
- # str = <<-EOT
680
- # Name,Value
681
- # foo,0
682
- # bar,1
683
- # baz,2
684
- # EOT
685
- # # With no header converter
686
- # table = CSV.parse(str, headers: true)
687
- # table.headers # => ["Name", "Value"]
688
- #
689
- # The value may be a header converter name (see [Stored
690
- # Converters](#class-CSV-label-Stored+Converters)):
691
- # table = CSV.parse(str, headers: true, header_converters: :downcase)
692
- # table.headers # => ["name", "value"]
693
- #
694
- # The value may be a converter list (see [Converter
695
- # Lists](#class-CSV-label-Converter+Lists)):
696
- # header_converters = [:downcase, :symbol]
697
- # table = CSV.parse(str, headers: true, header_converters: header_converters)
698
- # table.headers # => [:name, :value]
699
- #
700
- # The value may be a Proc custom converter (see [Custom Header
701
- # Converters](#class-CSV-label-Custom+Header+Converters)):
702
- # upcase_converter = proc {|field| field.upcase }
703
- # table = CSV.parse(str, headers: true, header_converters: upcase_converter)
704
- # table.headers # => ["NAME", "VALUE"]
705
- #
706
- # See also [Custom Header Converters](#class-CSV-label-Custom+Header+Converters)
707
- #
708
- # ###### Option `skip_blanks`
709
- #
710
- # Specifies a boolean that determines whether blank lines in the input will be
711
- # ignored; a line that contains a column separator is not considered to be
712
- # blank.
713
- #
714
- # Default value:
715
- # CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false
716
- #
717
- # See also option [skiplines](#class-CSV-label-Option+skip_lines).
718
- #
719
- # For examples in this section:
720
- # str = <<-EOT
721
- # foo,0
722
- #
723
- # bar,1
724
- # baz,2
725
- #
726
- # ,
727
- # EOT
728
- #
729
- # Using the default, `false`:
730
- # ary = CSV.parse(str)
731
- # ary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]]
732
- #
733
- # Using `true`:
734
- # ary = CSV.parse(str, skip_blanks: true)
735
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
736
- #
737
- # Using a truthy value:
738
- # ary = CSV.parse(str, skip_blanks: :foo)
739
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
740
- #
741
- # ###### Option `skip_lines`
742
- #
743
- # Specifies an object to use in identifying comment lines in the input that are
744
- # to be ignored:
745
- # * If a Regexp, ignores lines that match it.
746
- # * If a String, converts it to a Regexp, ignores lines that match it.
747
- # * If `nil`, no lines are considered to be comments.
748
- #
749
- # Default value:
750
- # CSV::DEFAULT_OPTIONS.fetch(:skip_lines) # => nil
751
- #
752
- # For examples in this section:
753
- # str = <<-EOT
754
- # # Comment
755
- # foo,0
756
- # bar,1
757
- # baz,2
758
- # # Another comment
759
- # EOT
760
- # str # => "# Comment\nfoo,0\nbar,1\nbaz,2\n# Another comment\n"
761
- #
762
- # Using the default, `nil`:
763
- # ary = CSV.parse(str)
764
- # ary # => [["# Comment"], ["foo", "0"], ["bar", "1"], ["baz", "2"], ["# Another comment"]]
765
- #
766
- # Using a Regexp:
767
- # ary = CSV.parse(str, skip_lines: /^#/)
768
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
769
- #
770
- # Using a String:
771
- # ary = CSV.parse(str, skip_lines: '#')
772
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
773
- #
774
- # ---
775
- #
776
- # Raises an exception if given an object that is not a Regexp, a String, or
777
- # `nil`:
778
- # # Raises ArgumentError (:skip_lines has to respond to #match: 0)
779
- # CSV.parse(str, skip_lines: 0)
780
- #
781
- # ###### Option `strip`
782
- #
783
- # Specifies the boolean value that determines whether whitespace is stripped
784
- # from each input field.
785
- #
786
- # Default value:
787
- # CSV::DEFAULT_OPTIONS.fetch(:strip) # => false
788
- #
789
- # With default value `false`:
790
- # ary = CSV.parse_line(' a , b ')
791
- # ary # => [" a ", " b "]
792
- #
793
- # With value `true`:
794
- # ary = CSV.parse_line(' a , b ', strip: true)
795
- # ary # => ["a", "b"]
796
- #
797
- # ###### Option `liberal_parsing`
798
- #
799
- # Specifies the boolean or hash value that determines whether CSV will attempt
800
- # to parse input not conformant with RFC 4180, such as double quotes in unquoted
801
- # fields.
802
- #
803
- # Default value:
804
- # CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false
805
- #
806
- # For the next two examples:
807
- # str = 'is,this "three, or four",fields'
808
- #
809
- # Without `liberal_parsing`:
810
- # # Raises CSV::MalformedCSVError (Illegal quoting in str 1.)
811
- # CSV.parse_line(str)
812
- #
813
- # With `liberal_parsing`:
814
- # ary = CSV.parse_line(str, liberal_parsing: true)
815
- # ary # => ["is", "this \"three", " or four\"", "fields"]
816
- #
817
- # Use the `backslash_quote` sub-option to parse values that use a backslash to
818
- # escape a double-quote character. This causes the parser to treat `\"` as if
819
- # it were `""`.
820
- #
821
- # For the next two examples:
822
- # str = 'Show,"Harry \"Handcuff\" Houdini, the one and only","Tampa Theater"'
823
- #
824
- # With `liberal_parsing`, but without the `backslash_quote` sub-option:
825
- # # Incorrect interpretation of backslash; incorrectly interprets the quoted comma as a field separator.
826
- # ary = CSV.parse_line(str, liberal_parsing: true)
827
- # ary # => ["Show", "\"Harry \\\"Handcuff\\\" Houdini", " the one and only\"", "Tampa Theater"]
828
- # puts ary[1] # => "Harry \"Handcuff\" Houdini
829
- #
830
- # With `liberal_parsing` and its `backslash_quote` sub-option:
831
- # ary = CSV.parse_line(str, liberal_parsing: { backslash_quote: true })
832
- # ary # => ["Show", "Harry \"Handcuff\" Houdini, the one and only", "Tampa Theater"]
833
- # puts ary[1] # => Harry "Handcuff" Houdini, the one and only
834
- #
835
- # ###### Option `nil_value`
836
- #
837
- # Specifies the object that is to be substituted for each null (no-text) field.
838
- #
839
- # Default value:
840
- # CSV::DEFAULT_OPTIONS.fetch(:nil_value) # => nil
841
- #
842
- # With the default, `nil`:
843
- # CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"]
844
- #
845
- # With a different object:
846
- # CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"]
847
- #
848
- # ###### Option `empty_value`
849
- #
850
- # Specifies the object that is to be substituted for each field that has an
851
- # empty String.
852
- #
853
- # Default value:
854
- # CSV::DEFAULT_OPTIONS.fetch(:empty_value) # => "" (empty string)
855
- #
856
- # With the default, `""`:
857
- # CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"]
858
- #
859
- # With a different object:
860
- # CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"]
861
- #
862
- # #### Options for Generating
863
- #
864
- # Options for generating, described in detail below, include:
865
- # * `row_sep`: Specifies the row separator; used to delimit rows.
866
- # * `col_sep`: Specifies the column separator; used to delimit fields.
867
- # * `quote_char`: Specifies the quote character; used to quote fields.
868
- # * `write_headers`: Specifies whether headers are to be written.
869
- # * `force_quotes`: Specifies whether each output field is to be quoted.
870
- # * `quote_empty`: Specifies whether each empty output field is to be quoted.
871
- # * `write_converters`: Specifies the field converters to be used in writing.
872
- # * `write_nil_value`: Specifies the object that is to be substituted for each
873
- # `nil`-valued field.
874
- # * `write_empty_value`: Specifies the object that is to be substituted for
875
- # each empty field.
876
- #
877
- # ###### Option `row_sep`
878
- #
879
- # Specifies the row separator, a String or the Symbol `:auto` (see below), to be
880
- # used for both parsing and generating.
881
- #
882
- # Default value:
883
- # CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto
884
- #
885
- # ---
886
- #
887
- # When `row_sep` is a String, that String becomes the row separator. The String
888
- # will be transcoded into the data's Encoding before use.
889
- #
890
- # Using `"\n"`:
891
- # row_sep = "\n"
892
- # str = CSV.generate(row_sep: row_sep) do |csv|
893
- # csv << [:foo, 0]
894
- # csv << [:bar, 1]
895
- # csv << [:baz, 2]
896
- # end
897
- # str # => "foo,0\nbar,1\nbaz,2\n"
898
- # ary = CSV.parse(str)
899
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
900
- #
901
- # Using `|` (pipe):
902
- # row_sep = '|'
903
- # str = CSV.generate(row_sep: row_sep) do |csv|
904
- # csv << [:foo, 0]
905
- # csv << [:bar, 1]
906
- # csv << [:baz, 2]
907
- # end
908
- # str # => "foo,0|bar,1|baz,2|"
909
- # ary = CSV.parse(str, row_sep: row_sep)
910
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
911
- #
912
- # Using `--` (two hyphens):
913
- # row_sep = '--'
914
- # str = CSV.generate(row_sep: row_sep) do |csv|
915
- # csv << [:foo, 0]
916
- # csv << [:bar, 1]
917
- # csv << [:baz, 2]
918
- # end
919
- # str # => "foo,0--bar,1--baz,2--"
920
- # ary = CSV.parse(str, row_sep: row_sep)
921
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
922
- #
923
- # Using `''` (empty string):
924
- # row_sep = ''
925
- # str = CSV.generate(row_sep: row_sep) do |csv|
926
- # csv << [:foo, 0]
927
- # csv << [:bar, 1]
928
- # csv << [:baz, 2]
929
- # end
930
- # str # => "foo,0bar,1baz,2"
931
- # ary = CSV.parse(str, row_sep: row_sep)
932
- # ary # => [["foo", "0bar", "1baz", "2"]]
933
- #
934
- # ---
935
- #
936
- # When `row_sep` is the Symbol `:auto` (the default), generating uses `"\n"` as
937
- # the row separator:
938
- # str = CSV.generate do |csv|
939
- # csv << [:foo, 0]
940
- # csv << [:bar, 1]
941
- # csv << [:baz, 2]
942
- # end
943
- # str # => "foo,0\nbar,1\nbaz,2\n"
944
- #
945
- # Parsing, on the other hand, invokes auto-discovery of the row separator.
946
- #
947
- # Auto-discovery reads ahead in the data looking for the next `\r\n`, `\n`, or
948
- # `\r` sequence. The sequence will be selected even if it occurs in a quoted
949
- # field, assuming that you would have the same line endings there.
950
- #
951
- # Example:
952
- # str = CSV.generate do |csv|
953
- # csv << [:foo, 0]
954
- # csv << [:bar, 1]
955
- # csv << [:baz, 2]
956
- # end
957
- # str # => "foo,0\nbar,1\nbaz,2\n"
958
- # ary = CSV.parse(str)
959
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
960
- #
961
- # The default `$INPUT_RECORD_SEPARATOR` (`$/`) is used if any of the following
962
- # is true:
963
- # * None of those sequences is found.
964
- # * Data is `ARGF`, `STDIN`, `STDOUT`, or `STDERR`.
965
- # * The stream is only available for output.
966
- #
967
- # Obviously, discovery takes a little time. Set manually if speed is important.
968
- # Also note that IO objects should be opened in binary mode on Windows if this
969
- # feature will be used as the line-ending translation can cause problems with
970
- # resetting the document position to where it was before the read ahead.
971
- #
972
- # ###### Option `col_sep`
973
- #
974
- # Specifies the String field separator to be used for both parsing and
975
- # generating. The String will be transcoded into the data's Encoding before use.
976
- #
977
- # Default value:
978
- # CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma)
979
- #
980
- # Using the default (comma):
981
- # str = CSV.generate do |csv|
982
- # csv << [:foo, 0]
983
- # csv << [:bar, 1]
984
- # csv << [:baz, 2]
985
- # end
986
- # str # => "foo,0\nbar,1\nbaz,2\n"
987
- # ary = CSV.parse(str)
988
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
989
- #
990
- # Using `:` (colon):
991
- # col_sep = ':'
992
- # str = CSV.generate(col_sep: col_sep) do |csv|
993
- # csv << [:foo, 0]
994
- # csv << [:bar, 1]
995
- # csv << [:baz, 2]
996
- # end
997
- # str # => "foo:0\nbar:1\nbaz:2\n"
998
- # ary = CSV.parse(str, col_sep: col_sep)
999
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1000
- #
1001
- # Using `::` (two colons):
1002
- # col_sep = '::'
1003
- # str = CSV.generate(col_sep: col_sep) do |csv|
1004
- # csv << [:foo, 0]
1005
- # csv << [:bar, 1]
1006
- # csv << [:baz, 2]
1007
- # end
1008
- # str # => "foo::0\nbar::1\nbaz::2\n"
1009
- # ary = CSV.parse(str, col_sep: col_sep)
1010
- # ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1011
- #
1012
- # Using `''` (empty string):
1013
- # col_sep = ''
1014
- # str = CSV.generate(col_sep: col_sep) do |csv|
1015
- # csv << [:foo, 0]
1016
- # csv << [:bar, 1]
1017
- # csv << [:baz, 2]
1018
- # end
1019
- # str # => "foo0\nbar1\nbaz2\n"
1020
- #
1021
- # ---
1022
- #
1023
- # Raises an exception if parsing with the empty String:
1024
- # col_sep = ''
1025
- # # Raises ArgumentError (:col_sep must be 1 or more characters: "")
1026
- # CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep)
1027
- #
1028
- # ###### Option `quote_char`
1029
- #
1030
- # Specifies the character (String of length 1) used used to quote fields in both
1031
- # parsing and generating. This String will be transcoded into the data's
1032
- # Encoding before use.
1033
- #
1034
- # Default value:
1035
- # CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote)
1036
- #
1037
- # This is useful for an application that incorrectly uses `'` (single-quote) to
1038
- # quote fields, instead of the correct `"` (double-quote).
1039
- #
1040
- # Using the default (double quote):
1041
- # str = CSV.generate do |csv|
1042
- # csv << ['foo', 0]
1043
- # csv << ["'bar'", 1]
1044
- # csv << ['"baz"', 2]
1045
- # end
1046
- # str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n"
1047
- # ary = CSV.parse(str)
1048
- # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
1049
- #
1050
- # Using `'` (single-quote):
1051
- # quote_char = "'"
1052
- # str = CSV.generate(quote_char: quote_char) do |csv|
1053
- # csv << ['foo', 0]
1054
- # csv << ["'bar'", 1]
1055
- # csv << ['"baz"', 2]
1056
- # end
1057
- # str # => "foo,0\n'''bar''',1\n\"baz\",2\n"
1058
- # ary = CSV.parse(str, quote_char: quote_char)
1059
- # ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
1060
- #
1061
- # ---
1062
- #
1063
- # Raises an exception if the String length is greater than 1:
1064
- # # Raises ArgumentError (:quote_char has to be nil or a single character String)
1065
- # CSV.new('', quote_char: 'xx')
1066
- #
1067
- # Raises an exception if the value is not a String:
1068
- # # Raises ArgumentError (:quote_char has to be nil or a single character String)
1069
- # CSV.new('', quote_char: :foo)
1070
- #
1071
- # ###### Option `write_headers`
1072
- #
1073
- # Specifies the boolean that determines whether a header row is included in the
1074
- # output; ignored if there are no headers.
1075
- #
1076
- # Default value:
1077
- # CSV::DEFAULT_OPTIONS.fetch(:write_headers) # => nil
1078
- #
1079
- # Without `write_headers`:
1080
- # file_path = 't.csv'
1081
- # CSV.open(file_path,'w',
1082
- # :headers => ['Name','Value']
1083
- # ) do |csv|
1084
- # csv << ['foo', '0']
1085
- # end
1086
- # CSV.open(file_path) do |csv|
1087
- # csv.shift
1088
- # end # => ["foo", "0"]
1089
- #
1090
- # With `write_headers`":
1091
- # CSV.open(file_path,'w',
1092
- # :write_headers => true,
1093
- # :headers => ['Name','Value']
1094
- # ) do |csv|
1095
- # csv << ['foo', '0']
1096
- # end
1097
- # CSV.open(file_path) do |csv|
1098
- # csv.shift
1099
- # end # => ["Name", "Value"]
1100
- #
1101
- # ###### Option `force_quotes`
1102
- #
1103
- # Specifies the boolean that determines whether each output field is to be
1104
- # double-quoted.
1105
- #
1106
- # Default value:
1107
- # CSV::DEFAULT_OPTIONS.fetch(:force_quotes) # => false
1108
- #
1109
- # For examples in this section:
1110
- # ary = ['foo', 0, nil]
1111
- #
1112
- # Using the default, `false`:
1113
- # str = CSV.generate_line(ary)
1114
- # str # => "foo,0,\n"
1115
- #
1116
- # Using `true`:
1117
- # str = CSV.generate_line(ary, force_quotes: true)
1118
- # str # => "\"foo\",\"0\",\"\"\n"
1119
- #
1120
- # ###### Option `quote_empty`
1121
- #
1122
- # Specifies the boolean that determines whether an empty value is to be
1123
- # double-quoted.
1124
- #
1125
- # Default value:
1126
- # CSV::DEFAULT_OPTIONS.fetch(:quote_empty) # => true
1127
- #
1128
- # With the default `true`:
1129
- # CSV.generate_line(['"', ""]) # => "\"\"\"\",\"\"\n"
1130
- #
1131
- # With `false`:
1132
- # CSV.generate_line(['"', ""], quote_empty: false) # => "\"\"\"\",\n"
1133
- #
1134
- # ###### Option `write_converters`
1135
- #
1136
- # Specifies converters to be used in generating fields. See [Write
1137
- # Converters](#class-CSV-label-Write+Converters)
1138
- #
1139
- # Default value:
1140
- # CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil
1141
- #
1142
- # With no write converter:
1143
- # str = CSV.generate_line(["\na\n", "\tb\t", " c "])
1144
- # str # => "\"\na\n\",\tb\t, c \n"
1145
- #
1146
- # With a write converter:
1147
- # strip_converter = proc {|field| field.strip }
1148
- # str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter)
1149
- # str # => "a,b,c\n"
1150
- #
1151
- # With two write converters (called in order):
1152
- # upcase_converter = proc {|field| field.upcase }
1153
- # downcase_converter = proc {|field| field.downcase }
1154
- # write_converters = [upcase_converter, downcase_converter]
1155
- # str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters)
1156
- # str # => "a,b,c\n"
1157
- #
1158
- # See also [Write Converters](#class-CSV-label-Write+Converters)
1159
- #
1160
- # ###### Option `write_nil_value`
1161
- #
1162
- # Specifies the object that is to be substituted for each `nil`-valued field.
1163
- #
1164
- # Default value:
1165
- # CSV::DEFAULT_OPTIONS.fetch(:write_nil_value) # => nil
1166
- #
1167
- # Without the option:
1168
- # str = CSV.generate_line(['a', nil, 'c', nil])
1169
- # str # => "a,,c,\n"
1170
- #
1171
- # With the option:
1172
- # str = CSV.generate_line(['a', nil, 'c', nil], write_nil_value: "x")
1173
- # str # => "a,x,c,x\n"
1174
- #
1175
- # ###### Option `write_empty_value`
1176
- #
1177
- # Specifies the object that is to be substituted for each field that has an
1178
- # empty String.
1179
- #
1180
- # Default value:
1181
- # CSV::DEFAULT_OPTIONS.fetch(:write_empty_value) # => ""
1182
- #
1183
- # Without the option:
1184
- # str = CSV.generate_line(['a', '', 'c', ''])
1185
- # str # => "a,\"\",c,\"\"\n"
1186
- #
1187
- # With the option:
1188
- # str = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x")
1189
- # str # => "a,x,c,x\n"
1190
- #
1191
- # ### CSV with Headers
1192
- #
1193
- # CSV allows to specify column names of CSV file, whether they are in data, or
1194
- # provided separately. If headers are specified, reading methods return an
1195
- # instance of CSV::Table, consisting of CSV::Row.
1196
- #
1197
- # # Headers are part of data
1198
- # data = CSV.parse(<<~ROWS, headers: true)
1199
- # Name,Department,Salary
1200
- # Bob,Engineering,1000
1201
- # Jane,Sales,2000
1202
- # John,Management,5000
1203
- # ROWS
1204
- #
1205
- # data.class #=> CSV::Table
1206
- # data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000">
1207
- # data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
1208
- #
1209
- # # Headers provided by developer
1210
- # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
1211
- # data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
1212
- #
1213
- # ### Converters
1214
- #
1215
- # By default, each value (field or header) parsed by CSV is formed into a
1216
- # String. You can use a *field* *converter* or *header* *converter* to
1217
- # intercept and modify the parsed values:
1218
- # * See [Field Converters](#class-CSV-label-Field+Converters).
1219
- # * See [Header Converters](#class-CSV-label-Header+Converters).
1220
- #
1221
- # Also by default, each value to be written during generation is written
1222
- # 'as-is'. You can use a *write* *converter* to modify values before writing.
1223
- # * See [Write Converters](#class-CSV-label-Write+Converters).
1224
- #
1225
- # #### Specifying Converters
1226
- #
1227
- # You can specify converters for parsing or generating in the `options` argument
1228
- # to various CSV methods:
1229
- # * Option `converters` for converting parsed field values.
1230
- # * Option `header_converters` for converting parsed header values.
1231
- # * Option `write_converters` for converting values to be written (generated).
1232
- #
1233
- # There are three forms for specifying converters:
1234
- # * A converter proc: executable code to be used for conversion.
1235
- # * A converter name: the name of a stored converter.
1236
- # * A converter list: an array of converter procs, converter names, and
1237
- # converter lists.
1238
- #
1239
- # ##### Converter Procs
1240
- #
1241
- # This converter proc, `strip_converter`, accepts a value `field` and returns
1242
- # `field.strip`:
1243
- # strip_converter = proc {|field| field.strip }
1244
- #
1245
- # In this call to `CSV.parse`, the keyword argument `converters:
1246
- # string_converter` specifies that:
1247
- # * Proc `string_converter` is to be called for each parsed field.
1248
- # * The converter's return value is to replace the `field` value.
1249
- # Example:
1250
- # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1251
- # array = CSV.parse(string, converters: strip_converter)
1252
- # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1253
- #
1254
- # A converter proc can receive a second argument, `field_info`, that contains
1255
- # details about the field. This modified `strip_converter` displays its
1256
- # arguments:
1257
- # strip_converter = proc do |field, field_info|
1258
- # p [field, field_info]
1259
- # field.strip
1260
- # end
1261
- # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1262
- # array = CSV.parse(string, converters: strip_converter)
1263
- # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1264
- #
1265
- # Output:
1266
- # [" foo ", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
1267
- # [" 0 ", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
1268
- # [" bar ", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
1269
- # [" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
1270
- # [" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
1271
- # [" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
1272
- #
1273
- # Each CSV::FieldInfo object shows:
1274
- # * The 0-based field index.
1275
- # * The 1-based line index.
1276
- # * The field header, if any.
1277
- #
1278
- # ##### Stored Converters
1279
- #
1280
- # A converter may be given a name and stored in a structure where the parsing
1281
- # methods can find it by name.
1282
- #
1283
- # The storage structure for field converters is the Hash CSV::Converters. It has
1284
- # several built-in converter procs:
1285
- # * `:integer`: converts each String-embedded integer into a true Integer.
1286
- # * `:float`: converts each String-embedded float into a true Float.
1287
- # * `:date`: converts each String-embedded date into a true Date.
1288
- # * `:date_time`: converts each String-embedded date-time into a true DateTime
1289
- # . This example creates a converter proc, then stores it:
1290
- # strip_converter = proc {|field| field.strip }
1291
- # CSV::Converters[:strip] = strip_converter
1292
- #
1293
- # Then the parsing method call can refer to the converter by its name, `:strip`:
1294
- # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1295
- # array = CSV.parse(string, converters: :strip)
1296
- # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1297
- #
1298
- # The storage structure for header converters is the Hash CSV::HeaderConverters,
1299
- # which works in the same way. It also has built-in converter procs:
1300
- # * `:downcase`: Downcases each header.
1301
- # * `:symbol`: Converts each header to a Symbol.
1302
- #
1303
- # There is no such storage structure for write headers.
1304
- #
1305
- # In order for the parsing methods to access stored converters in
1306
- # non-main-Ractors, the storage structure must be made shareable first.
1307
- # Therefore, `Ractor.make_shareable(CSV::Converters)` and
1308
- # `Ractor.make_shareable(CSV::HeaderConverters)` must be called before the
1309
- # creation of Ractors that use the converters stored in these structures. (Since
1310
- # making the storage structures shareable involves freezing them, any custom
1311
- # converters that are to be used must be added first.)
1312
- #
1313
- # ##### Converter Lists
1314
- #
1315
- # A *converter* *list* is an Array that may include any assortment of:
1316
- # * Converter procs.
1317
- # * Names of stored converters.
1318
- # * Nested converter lists.
1319
- #
1320
- # Examples:
1321
- # numeric_converters = [:integer, :float]
1322
- # date_converters = [:date, :date_time]
1323
- # [numeric_converters, strip_converter]
1324
- # [strip_converter, date_converters, :float]
1325
- #
1326
- # Like a converter proc, a converter list may be named and stored in either
1327
- # CSV::Converters or CSV::HeaderConverters:
1328
- # CSV::Converters[:custom] = [strip_converter, date_converters, :float]
1329
- # CSV::HeaderConverters[:custom] = [:downcase, :symbol]
1330
- #
1331
- # There are two built-in converter lists:
1332
- # CSV::Converters[:numeric] # => [:integer, :float]
1333
- # CSV::Converters[:all] # => [:date_time, :numeric]
1334
- #
1335
- # #### Field Converters
1336
- #
1337
- # With no conversion, all parsed fields in all rows become Strings:
1338
- # string = "foo,0\nbar,1\nbaz,2\n"
1339
- # ary = CSV.parse(string)
1340
- # ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1341
- #
1342
- # When you specify a field converter, each parsed field is passed to the
1343
- # converter; its return value becomes the stored value for the field. A
1344
- # converter might, for example, convert an integer embedded in a String into a
1345
- # true Integer. (In fact, that's what built-in field converter `:integer` does.)
1346
- #
1347
- # There are three ways to use field converters.
1348
- #
1349
- # * Using option [converters](#class-CSV-label-Option+converters) with a
1350
- # parsing method:
1351
- # ary = CSV.parse(string, converters: :integer)
1352
- # ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]]
1353
- #
1354
- # * Using option [converters](#class-CSV-label-Option+converters) with a new
1355
- # CSV instance:
1356
- # csv = CSV.new(string, converters: :integer)
1357
- # # Field converters in effect:
1358
- # csv.converters # => [:integer]
1359
- # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
1360
- #
1361
- # * Using method #convert to add a field converter to a CSV instance:
1362
- # csv = CSV.new(string)
1363
- # # Add a converter.
1364
- # csv.convert(:integer)
1365
- # csv.converters # => [:integer]
1366
- # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
1367
- #
1368
- # Installing a field converter does not affect already-read rows:
1369
- # csv = CSV.new(string)
1370
- # csv.shift # => ["foo", "0"]
1371
- # # Add a converter.
1372
- # csv.convert(:integer)
1373
- # csv.converters # => [:integer]
1374
- # csv.read # => [["bar", 1], ["baz", 2]]
1375
- #
1376
- # There are additional built-in converters, and custom converters are also
1377
- # supported.
1378
- #
1379
- # ##### Built-In Field Converters
1380
- #
1381
- # The built-in field converters are in Hash CSV::Converters:
1382
- # * Each key is a field converter name.
1383
- # * Each value is one of:
1384
- # * A Proc field converter.
1385
- # * An Array of field converter names.
1386
- #
1387
- # Display:
1388
- # CSV::Converters.each_pair do |name, value|
1389
- # if value.kind_of?(Proc)
1390
- # p [name, value.class]
1391
- # else
1392
- # p [name, value]
1393
- # end
1394
- # end
1395
- #
1396
- # Output:
1397
- # [:integer, Proc]
1398
- # [:float, Proc]
1399
- # [:numeric, [:integer, :float]]
1400
- # [:date, Proc]
1401
- # [:date_time, Proc]
1402
- # [:all, [:date_time, :numeric]]
1403
- #
1404
- # Each of these converters transcodes values to UTF-8 before attempting
1405
- # conversion. If a value cannot be transcoded to UTF-8 the conversion will fail
1406
- # and the value will remain unconverted.
1407
- #
1408
- # Converter `:integer` converts each field that Integer() accepts:
1409
- # data = '0,1,2,x'
1410
- # # Without the converter
1411
- # csv = CSV.parse_line(data)
1412
- # csv # => ["0", "1", "2", "x"]
1413
- # # With the converter
1414
- # csv = CSV.parse_line(data, converters: :integer)
1415
- # csv # => [0, 1, 2, "x"]
1416
- #
1417
- # Converter `:float` converts each field that Float() accepts:
1418
- # data = '1.0,3.14159,x'
1419
- # # Without the converter
1420
- # csv = CSV.parse_line(data)
1421
- # csv # => ["1.0", "3.14159", "x"]
1422
- # # With the converter
1423
- # csv = CSV.parse_line(data, converters: :float)
1424
- # csv # => [1.0, 3.14159, "x"]
1425
- #
1426
- # Converter `:numeric` converts with both `:integer` and `:float`..
1427
- #
1428
- # Converter `:date` converts each field that Date::parse accepts:
1429
- # data = '2001-02-03,x'
1430
- # # Without the converter
1431
- # csv = CSV.parse_line(data)
1432
- # csv # => ["2001-02-03", "x"]
1433
- # # With the converter
1434
- # csv = CSV.parse_line(data, converters: :date)
1435
- # csv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"]
1436
- #
1437
- # Converter `:date_time` converts each field that DateTime::parse accepts:
1438
- # data = '2020-05-07T14:59:00-05:00,x'
1439
- # # Without the converter
1440
- # csv = CSV.parse_line(data)
1441
- # csv # => ["2020-05-07T14:59:00-05:00", "x"]
1442
- # # With the converter
1443
- # csv = CSV.parse_line(data, converters: :date_time)
1444
- # csv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"]
1445
- #
1446
- # Converter `:numeric` converts with both `:date_time` and `:numeric`..
1447
- #
1448
- # As seen above, method #convert adds converters to a CSV instance, and method
1449
- # #converters returns an Array of the converters in effect:
1450
- # csv = CSV.new('0,1,2')
1451
- # csv.converters # => []
1452
- # csv.convert(:integer)
1453
- # csv.converters # => [:integer]
1454
- # csv.convert(:date)
1455
- # csv.converters # => [:integer, :date]
1456
- #
1457
- # ##### Custom Field Converters
1458
- #
1459
- # You can define a custom field converter:
1460
- # strip_converter = proc {|field| field.strip }
1461
- # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1462
- # array = CSV.parse(string, converters: strip_converter)
1463
- # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1464
- #
1465
- # You can register the converter in Converters Hash, which allows you to refer
1466
- # to it by name:
1467
- # CSV::Converters[:strip] = strip_converter
1468
- # string = " foo , 0 \n bar , 1 \n baz , 2 \n"
1469
- # array = CSV.parse(string, converters: :strip)
1470
- # array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1471
- #
1472
- # #### Header Converters
1473
- #
1474
- # Header converters operate only on headers (and not on other rows).
1475
- #
1476
- # There are three ways to use header converters; these examples use built-in
1477
- # header converter `:downcase`, which downcases each parsed header.
1478
- #
1479
- # * Option `header_converters` with a singleton parsing method:
1480
- # string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
1481
- # tbl = CSV.parse(string, headers: true, header_converters: :downcase)
1482
- # tbl.class # => CSV::Table
1483
- # tbl.headers # => ["name", "count"]
1484
- #
1485
- # * Option `header_converters` with a new CSV instance:
1486
- # csv = CSV.new(string, header_converters: :downcase)
1487
- # # Header converters in effect:
1488
- # csv.header_converters # => [:downcase]
1489
- # tbl = CSV.parse(string, headers: true)
1490
- # tbl.headers # => ["Name", "Count"]
1491
- #
1492
- # * Method #header_convert adds a header converter to a CSV instance:
1493
- # csv = CSV.new(string)
1494
- # # Add a header converter.
1495
- # csv.header_convert(:downcase)
1496
- # csv.header_converters # => [:downcase]
1497
- # tbl = CSV.parse(string, headers: true)
1498
- # tbl.headers # => ["Name", "Count"]
1499
- #
1500
- # ##### Built-In Header Converters
1501
- #
1502
- # The built-in header converters are in Hash CSV::HeaderConverters. The keys
1503
- # there are the names of the converters:
1504
- # CSV::HeaderConverters.keys # => [:downcase, :symbol]
1505
- #
1506
- # Converter `:downcase` converts each header by downcasing it:
1507
- # string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
1508
- # tbl = CSV.parse(string, headers: true, header_converters: :downcase)
1509
- # tbl.class # => CSV::Table
1510
- # tbl.headers # => ["name", "count"]
1511
- #
1512
- # Converter `:symbol` converts each header by making it into a Symbol:
1513
- # string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
1514
- # tbl = CSV.parse(string, headers: true, header_converters: :symbol)
1515
- # tbl.headers # => [:name, :count]
1516
- #
1517
- # Details:
1518
- # * Strips leading and trailing whitespace.
1519
- # * Downcases the header.
1520
- # * Replaces embedded spaces with underscores.
1521
- # * Removes non-word characters.
1522
- # * Makes the string into a Symbol.
1523
- #
1524
- # ##### Custom Header Converters
1525
- #
1526
- # You can define a custom header converter:
1527
- # upcase_converter = proc {|header| header.upcase }
1528
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
1529
- # table = CSV.parse(string, headers: true, header_converters: upcase_converter)
1530
- # table # => #<CSV::Table mode:col_or_row row_count:4>
1531
- # table.headers # => ["NAME", "VALUE"]
1532
- #
1533
- # You can register the converter in HeaderConverters Hash, which allows you to
1534
- # refer to it by name:
1535
- # CSV::HeaderConverters[:upcase] = upcase_converter
1536
- # table = CSV.parse(string, headers: true, header_converters: :upcase)
1537
- # table # => #<CSV::Table mode:col_or_row row_count:4>
1538
- # table.headers # => ["NAME", "VALUE"]
1539
- #
1540
- # ##### Write Converters
1541
- #
1542
- # When you specify a write converter for generating CSV, each field to be
1543
- # written is passed to the converter; its return value becomes the new value for
1544
- # the field. A converter might, for example, strip whitespace from a field.
1545
- #
1546
- # Using no write converter (all fields unmodified):
1547
- # output_string = CSV.generate do |csv|
1548
- # csv << [' foo ', 0]
1549
- # csv << [' bar ', 1]
1550
- # csv << [' baz ', 2]
1551
- # end
1552
- # output_string # => " foo ,0\n bar ,1\n baz ,2\n"
1553
- #
1554
- # Using option `write_converters` with two custom write converters:
1555
- # strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
1556
- # upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field }
1557
- # write_converters = [strip_converter, upcase_converter]
1558
- # output_string = CSV.generate(write_converters: write_converters) do |csv|
1559
- # csv << [' foo ', 0]
1560
- # csv << [' bar ', 1]
1561
- # csv << [' baz ', 2]
1562
- # end
1563
- # output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
1564
- #
1565
- # ### Character Encodings (M17n or Multilingualization)
1566
- #
1567
- # This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
1568
- # or String object being read from or written to. Your data is never transcoded
1569
- # (unless you ask Ruby to transcode it for you) and will literally be parsed in
1570
- # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
1571
- # Encoding of your data. This is accomplished by transcoding the parser itself
1572
- # into your Encoding.
1573
- #
1574
- # Some transcoding must take place, of course, to accomplish this multiencoding
1575
- # support. For example, `:col_sep`, `:row_sep`, and `:quote_char` must be
1576
- # transcoded to match your data. Hopefully this makes the entire process feel
1577
- # transparent, since CSV's defaults should just magically work for your data.
1578
- # However, you can set these values manually in the target Encoding to avoid the
1579
- # translation.
1580
- #
1581
- # It's also important to note that while all of CSV's core parser is now
1582
- # Encoding agnostic, some features are not. For example, the built-in converters
1583
- # will try to transcode data to UTF-8 before making conversions. Again, you can
1584
- # provide custom converters that are aware of your Encodings to avoid this
1585
- # translation. It's just too hard for me to support native conversions in all of
1586
- # Ruby's Encodings.
1587
- #
1588
- # Anyway, the practical side of this is simple: make sure IO and String objects
1589
- # passed into CSV have the proper Encoding set and everything should just work.
1590
- # CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(),
1591
- # CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
1592
- #
1593
- # One minor exception comes when generating CSV into a String with an Encoding
1594
- # that is not ASCII compatible. There's no existing data for CSV to use to
1595
- # prepare itself and thus you will probably need to manually specify the desired
1596
- # Encoding for most of those cases. It will try to guess using the fields in a
1597
- # row of output though, when using CSV::generate_line() or Array#to_csv().
1598
- #
1599
- # I try to point out any other Encoding issues in the documentation of methods
1600
- # as they come up.
1601
- #
1602
- # This has been tested to the best of my ability with all non-"dummy" Encodings
1603
- # Ruby ships with. However, it is brave new code and may have some bugs. Please
1604
- # feel free to [report](mailto:james@grayproductions.net) any issues you find
1605
- # with it.
1606
- #
1607
- class CSV < Object
1608
- include Enumerable[untyped]
1609
- extend Forwardable
1610
-
1611
- # <!--
1612
- # rdoc-file=lib/csv.rb
1613
- # - foreach(path_or_io, mode='r', **options) {|row| ... )
1614
- # - foreach(path_or_io, mode='r', **options) -> new_enumerator
1615
- # -->
1616
- # Calls the block with each row read from source `path_or_io`.
1617
- #
1618
- # Path input without headers:
1619
- #
1620
- # string = "foo,0\nbar,1\nbaz,2\n"
1621
- # in_path = 't.csv'
1622
- # File.write(in_path, string)
1623
- # CSV.foreach(in_path) {|row| p row }
1624
- #
1625
- # Output:
1626
- #
1627
- # ["foo", "0"]
1628
- # ["bar", "1"]
1629
- # ["baz", "2"]
1630
- #
1631
- # Path input with headers:
1632
- #
1633
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
1634
- # in_path = 't.csv'
1635
- # File.write(in_path, string)
1636
- # CSV.foreach(in_path, headers: true) {|row| p row }
1637
- #
1638
- # Output:
1639
- #
1640
- # <CSV::Row "Name":"foo" "Value":"0">
1641
- # <CSV::Row "Name":"bar" "Value":"1">
1642
- # <CSV::Row "Name":"baz" "Value":"2">
1643
- #
1644
- # IO stream input without headers:
1645
- #
1646
- # string = "foo,0\nbar,1\nbaz,2\n"
1647
- # path = 't.csv'
1648
- # File.write(path, string)
1649
- # File.open('t.csv') do |in_io|
1650
- # CSV.foreach(in_io) {|row| p row }
1651
- # end
1652
- #
1653
- # Output:
1654
- #
1655
- # ["foo", "0"]
1656
- # ["bar", "1"]
1657
- # ["baz", "2"]
1658
- #
1659
- # IO stream input with headers:
1660
- #
1661
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
1662
- # path = 't.csv'
1663
- # File.write(path, string)
1664
- # File.open('t.csv') do |in_io|
1665
- # CSV.foreach(in_io, headers: true) {|row| p row }
1666
- # end
1667
- #
1668
- # Output:
1669
- #
1670
- # <CSV::Row "Name":"foo" "Value":"0">
1671
- # <CSV::Row "Name":"bar" "Value":"1">
1672
- # <CSV::Row "Name":"baz" "Value":"2">
1673
- #
1674
- # With no block given, returns an Enumerator:
1675
- #
1676
- # string = "foo,0\nbar,1\nbaz,2\n"
1677
- # path = 't.csv'
1678
- # File.write(path, string)
1679
- # CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
1680
- #
1681
- # Arguments:
1682
- # * Argument `path_or_io` must be a file path or an IO stream.
1683
- # * Argument `mode`, if given, must be a File mode. See [Access
1684
- # Modes](rdoc-ref:File@Access+Modes).
1685
- # * Arguments `**options` must be keyword options. See [Options for
1686
- # Parsing](#class-CSV-label-Options+for+Parsing).
1687
- # * This method optionally accepts an additional `:encoding` option that you
1688
- # can use to specify the Encoding of the data read from `path` or `io`. You
1689
- # must provide this unless your data is in the encoding given by
1690
- # `Encoding::default_external`. Parsing will use this to determine how to
1691
- # parse the data. You may provide a second Encoding to have the data
1692
- # transcoded as it is read. For example,
1693
- # encoding: 'UTF-32BE:UTF-8'
1694
- #
1695
- # would read `UTF-32BE` data from the file but transcode it to `UTF-8`
1696
- # before parsing.
1697
- #
1698
- def self.foreach: (String | IO path, ?String mode, headers: true | :first_row | Array[untyped] | String, **untyped options) { (::CSV::Row arg0) -> void } -> void
1699
- | (String | IO path, ?String mode, headers: true | :first_row | Array[untyped] | String, **untyped options) -> Enumerator[::CSV::Row, void]
1700
- | (String | IO path, ?String mode, **untyped options) { (::Array[String?] arg0) -> void } -> void
1701
- | (String | IO path, ?String mode, **untyped options) -> Enumerator[::Array[String?], void]
1702
-
1703
- # <!--
1704
- # rdoc-file=lib/csv.rb
1705
- # - open(path_or_io, mode = "rb", **options ) -> new_csv
1706
- # - open(path_or_io, mode = "rb", **options ) { |csv| ... } -> object
1707
- # -->
1708
- # possible options elements:
1709
- # keyword form:
1710
- # :invalid => nil # raise error on invalid byte sequence (default)
1711
- # :invalid => :replace # replace invalid byte sequence
1712
- # :undef => :replace # replace undefined conversion
1713
- # :replace => string # replacement string ("?" or "\uFFFD" if not specified)
1714
- #
1715
- # * Argument +path_or_io+, must be a file path or an \IO stream.
1716
- # * Argument +io+ should be an IO object that is:
1717
- # * Open for reading; on return, the IO object will be closed.
1718
- # * Positioned at the beginning.
1719
- # To position at the end, for appending, use method CSV.generate.
1720
- # For any other positioning, pass a preset \StringIO object instead.
1721
- # * Argument +mode+, if given, must be a \File mode.
1722
- # See {Access Modes}[https://docs.ruby-lang.org/en/master/File.html#class-File-label-Access+Modes].
1723
- # * Arguments <tt>**options</tt> must be keyword options.
1724
- # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
1725
- # * This method optionally accepts an additional <tt>:encoding</tt> option
1726
- # that you can use to specify the Encoding of the data read from +path+ or +io+.
1727
- # You must provide this unless your data is in the encoding
1728
- # given by <tt>Encoding::default_external</tt>.
1729
- # Parsing will use this to determine how to parse the data.
1730
- # You may provide a second Encoding to
1731
- # have the data transcoded as it is read. For example,
1732
- # encoding: 'UTF-32BE:UTF-8'
1733
- # would read +UTF-32BE+ data from the file
1734
- # but transcode it to +UTF-8+ before parsing.
1735
- #
1736
- # ---
1737
- #
1738
- # These examples assume prior execution of:
1739
- # string = "foo,0\nbar,1\nbaz,2\n"
1740
- # path = 't.csv'
1741
- # File.write(path, string)
1742
- #
1743
- # string_io = StringIO.new
1744
- # string_io << "foo,0\nbar,1\nbaz,2\n"
1745
- #
1746
- # ---
1747
- #
1748
- # With no block given, returns a new \CSV object.
1749
- #
1750
- # Create a \CSV object using a file path:
1751
- # csv = CSV.open(path)
1752
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1753
- #
1754
- # Create a \CSV object using an open \File:
1755
- # csv = CSV.open(File.open(path))
1756
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1757
- #
1758
- # Create a \CSV object using a \StringIO:
1759
- # csv = CSV.open(string_io)
1760
- # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1761
- # ---
1762
- #
1763
- # With a block given, calls the block with the created \CSV object;
1764
- # returns the block's return value:
1765
- #
1766
- # Using a file path:
1767
- # csv = CSV.open(path) {|csv| p csv}
1768
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1769
- # Output:
1770
- # #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1771
- #
1772
- # Using an open \File:
1773
- # csv = CSV.open(File.open(path)) {|csv| p csv}
1774
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1775
- # Output:
1776
- # #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1777
- #
1778
- # Using a \StringIO:
1779
- # csv = CSV.open(string_io) {|csv| p csv}
1780
- # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1781
- # Output:
1782
- # #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1783
- # ---
1784
- #
1785
- # Raises an exception if the argument is not a \String object or \IO object:
1786
- # # Raises TypeError (no implicit conversion of Symbol into String)
1787
- # CSV.open(:foo)
1788
- #
1789
- def self.open: (String | _ToPath | IO | StringIO filename_or_io,
1790
- ?String mode,
1791
- ?newline: untyped,
1792
- ?invalid: nil | :replace,
1793
- ?undef: :replace,
1794
- ?replace: String,
1795
- ?encoding: Encoding | String,
1796
- **untyped options) ?{ (instance) -> void } -> instance
1797
-
1798
- # <!--
1799
- # rdoc-file=lib/csv.rb
1800
- # - CSV.new(string)
1801
- # - CSV.new(io)
1802
- # - CSV.new(string, **options)
1803
- # - CSV.new(io, **options)
1804
- # -->
1805
- # Returns the new CSV object created using `string` or `io` and the specified
1806
- # `options`.
1807
- #
1808
- # * Argument `string` should be a String object; it will be put into a new
1809
- # StringIO object positioned at the beginning.
1810
- # * Argument `io` should be an IO object that is:
1811
- # * Open for reading; on return, the IO object will be closed.
1812
- # * Positioned at the beginning. To position at the end, for appending,
1813
- # use method CSV.generate. For any other positioning, pass a preset
1814
- # StringIO object instead.
1815
- # * Argument `options`: See:
1816
- # * [Options for Parsing](#class-CSV-label-Options+for+Parsing)
1817
- # * [Options for Generating](#class-CSV-label-Options+for+Generating)
1818
- # For performance reasons, the options cannot be overridden in a CSV object,
1819
- # so those specified here will endure.
1820
- #
1821
- # In addition to the CSV instance methods, several IO methods are delegated. See
1822
- # [Delegated Methods](#class-CSV-label-Delegated+Methods).
1823
- #
1824
- # ---
1825
- #
1826
- # Create a CSV object from a String object:
1827
- # csv = CSV.new('foo,0')
1828
- # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1829
- #
1830
- # Create a CSV object from a File object:
1831
- # File.write('t.csv', 'foo,0')
1832
- # csv = CSV.new(File.open('t.csv'))
1833
- # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
1834
- #
1835
- # ---
1836
- #
1837
- # Raises an exception if the argument is `nil`:
1838
- # # Raises ArgumentError (Cannot parse nil as CSV):
1839
- # CSV.new(nil)
1840
- #
1841
- def initialize: (?String | IO | StringIO io, ?::Hash[Symbol, untyped] options) -> void
1842
-
1843
- # <!--
1844
- # rdoc-file=lib/csv.rb
1845
- # - parse(string) -> array_of_arrays
1846
- # - parse(io) -> array_of_arrays
1847
- # - parse(string, headers: ..., **options) -> csv_table
1848
- # - parse(io, headers: ..., **options) -> csv_table
1849
- # - parse(string, **options) {|row| ... }
1850
- # - parse(io, **options) {|row| ... }
1851
- # -->
1852
- # Parses `string` or `io` using the specified `options`.
1853
- #
1854
- # * Argument `string` should be a String object; it will be put into a new
1855
- # StringIO object positioned at the beginning.
1856
- # * Argument `io` should be an IO object that is:
1857
- # * Open for reading; on return, the IO object will be closed.
1858
- # * Positioned at the beginning. To position at the end, for appending,
1859
- # use method CSV.generate. For any other positioning, pass a preset
1860
- # StringIO object instead.
1861
- # * Argument `options`: see [Options for
1862
- # Parsing](#class-CSV-label-Options+for+Parsing)
1863
- #
1864
- # ###### Without Option `headers`
1865
- #
1866
- # Without {option `headers`[}](#class-CSV-label-Option+headers) case.
1867
- #
1868
- # These examples assume prior execution of:
1869
- # string = "foo,0\nbar,1\nbaz,2\n"
1870
- # path = 't.csv'
1871
- # File.write(path, string)
1872
- #
1873
- # ---
1874
- #
1875
- # With no block given, returns an Array of Arrays formed from the source.
1876
- #
1877
- # Parse a String:
1878
- # a_of_a = CSV.parse(string)
1879
- # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1880
- #
1881
- # Parse an open File:
1882
- # a_of_a = File.open(path) do |file|
1883
- # CSV.parse(file)
1884
- # end
1885
- # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
1886
- #
1887
- # ---
1888
- #
1889
- # With a block given, calls the block with each parsed row:
1890
- #
1891
- # Parse a String:
1892
- # CSV.parse(string) {|row| p row }
1893
- #
1894
- # Output:
1895
- # ["foo", "0"]
1896
- # ["bar", "1"]
1897
- # ["baz", "2"]
1898
- #
1899
- # Parse an open File:
1900
- # File.open(path) do |file|
1901
- # CSV.parse(file) {|row| p row }
1902
- # end
1903
- #
1904
- # Output:
1905
- # ["foo", "0"]
1906
- # ["bar", "1"]
1907
- # ["baz", "2"]
1908
- #
1909
- # ###### With Option `headers`
1910
- #
1911
- # With {option `headers`[}](#class-CSV-label-Option+headers) case.
1912
- #
1913
- # These examples assume prior execution of:
1914
- # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
1915
- # path = 't.csv'
1916
- # File.write(path, string)
1917
- #
1918
- # ---
1919
- #
1920
- # With no block given, returns a CSV::Table object formed from the source.
1921
- #
1922
- # Parse a String:
1923
- # csv_table = CSV.parse(string, headers: ['Name', 'Count'])
1924
- # csv_table # => #<CSV::Table mode:col_or_row row_count:5>
1925
- #
1926
- # Parse an open File:
1927
- # csv_table = File.open(path) do |file|
1928
- # CSV.parse(file, headers: ['Name', 'Count'])
1929
- # end
1930
- # csv_table # => #<CSV::Table mode:col_or_row row_count:4>
1931
- #
1932
- # ---
1933
- #
1934
- # With a block given, calls the block with each parsed row, which has been
1935
- # formed into a CSV::Row object:
1936
- #
1937
- # Parse a String:
1938
- # CSV.parse(string, headers: ['Name', 'Count']) {|row| p row }
1939
- #
1940
- # Output:
1941
- # # <CSV::Row "Name":"foo" "Count":"0">
1942
- # # <CSV::Row "Name":"bar" "Count":"1">
1943
- # # <CSV::Row "Name":"baz" "Count":"2">
1944
- #
1945
- # Parse an open File:
1946
- # File.open(path) do |file|
1947
- # CSV.parse(file, headers: ['Name', 'Count']) {|row| p row }
1948
- # end
1949
- #
1950
- # Output:
1951
- # # <CSV::Row "Name":"foo" "Count":"0">
1952
- # # <CSV::Row "Name":"bar" "Count":"1">
1953
- # # <CSV::Row "Name":"baz" "Count":"2">
1954
- #
1955
- # ---
1956
- #
1957
- # Raises an exception if the argument is not a String object or IO object:
1958
- # # Raises NoMethodError (undefined method `close' for :foo:Symbol)
1959
- # CSV.parse(:foo)
1960
- #
1961
- def self.parse: (String str, ?::Hash[Symbol, untyped] options) ?{ (::Array[String?] arg0) -> void } -> ::Array[::Array[String?]]?
1962
-
1963
- # <!--
1964
- # rdoc-file=lib/csv.rb
1965
- # - CSV.parse_line(string) -> new_array or nil
1966
- # - CSV.parse_line(io) -> new_array or nil
1967
- # - CSV.parse_line(string, **options) -> new_array or nil
1968
- # - CSV.parse_line(io, **options) -> new_array or nil
1969
- # - CSV.parse_line(string, headers: true, **options) -> csv_row or nil
1970
- # - CSV.parse_line(io, headers: true, **options) -> csv_row or nil
1971
- # -->
1972
- # Returns the data created by parsing the first line of `string` or `io` using
1973
- # the specified `options`.
1974
- #
1975
- # * Argument `string` should be a String object; it will be put into a new
1976
- # StringIO object positioned at the beginning.
1977
- # * Argument `io` should be an IO object that is:
1978
- # * Open for reading; on return, the IO object will be closed.
1979
- # * Positioned at the beginning. To position at the end, for appending,
1980
- # use method CSV.generate. For any other positioning, pass a preset
1981
- # StringIO object instead.
1982
- # * Argument `options`: see [Options for
1983
- # Parsing](#class-CSV-label-Options+for+Parsing)
1984
- #
1985
- # ###### Without Option `headers`
1986
- #
1987
- # Without option `headers`, returns the first row as a new Array.
1988
- #
1989
- # These examples assume prior execution of:
1990
- # string = "foo,0\nbar,1\nbaz,2\n"
1991
- # path = 't.csv'
1992
- # File.write(path, string)
1993
- #
1994
- # Parse the first line from a String object:
1995
- # CSV.parse_line(string) # => ["foo", "0"]
1996
- #
1997
- # Parse the first line from a File object:
1998
- # File.open(path) do |file|
1999
- # CSV.parse_line(file) # => ["foo", "0"]
2000
- # end # => ["foo", "0"]
2001
- #
2002
- # Returns `nil` if the argument is an empty String:
2003
- # CSV.parse_line('') # => nil
2004
- #
2005
- # ###### With Option `headers`
2006
- #
2007
- # With {option `headers`[}](#class-CSV-label-Option+headers), returns the first
2008
- # row as a CSV::Row object.
2009
- #
2010
- # These examples assume prior execution of:
2011
- # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
2012
- # path = 't.csv'
2013
- # File.write(path, string)
2014
- #
2015
- # Parse the first line from a String object:
2016
- # CSV.parse_line(string, headers: true) # => #<CSV::Row "Name":"foo" "Count":"0">
2017
- #
2018
- # Parse the first line from a File object:
2019
- # File.open(path) do |file|
2020
- # CSV.parse_line(file, headers: true)
2021
- # end # => #<CSV::Row "Name":"foo" "Count":"0">
2022
- #
2023
- # ---
2024
- #
2025
- # Raises an exception if the argument is `nil`:
2026
- # # Raises ArgumentError (Cannot parse nil as CSV):
2027
- # CSV.parse_line(nil)
2028
- #
2029
- def self.parse_line: (String str, ?::Hash[Symbol, untyped] options) -> ::Array[String?]?
2030
-
2031
- # <!--
2032
- # rdoc-file=lib/csv.rb
2033
- # - csv.read -> array or csv_table
2034
- # -->
2035
- # Forms the remaining rows from `self` into:
2036
- # * A CSV::Table object, if headers are in use.
2037
- # * An Array of Arrays, otherwise.
2038
- #
2039
- # The data source must be opened for reading.
2040
- #
2041
- # Without headers:
2042
- # string = "foo,0\nbar,1\nbaz,2\n"
2043
- # path = 't.csv'
2044
- # File.write(path, string)
2045
- # csv = CSV.open(path)
2046
- # csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
2047
- #
2048
- # With headers:
2049
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2050
- # path = 't.csv'
2051
- # File.write(path, string)
2052
- # csv = CSV.open(path, headers: true)
2053
- # csv.read # => #<CSV::Table mode:col_or_row row_count:4>
2054
- #
2055
- # ---
2056
- #
2057
- # Raises an exception if the source is not opened for reading:
2058
- # string = "foo,0\nbar,1\nbaz,2\n"
2059
- # csv = CSV.new(string)
2060
- # csv.close
2061
- # # Raises IOError (not opened for reading)
2062
- # csv.read
2063
- #
2064
- def read: () -> ::Array[::Array[String?]]
2065
-
2066
- # <!--
2067
- # rdoc-file=lib/csv.rb
2068
- # - readline()
2069
- # -->
2070
- #
2071
- def readline: () -> ::Array[String?]?
2072
-
2073
- # <!--
2074
- # rdoc-file=lib/csv.rb
2075
- # - read(source, **options) -> array_of_arrays
2076
- # - read(source, headers: true, **options) -> csv_table
2077
- # -->
2078
- # Opens the given `source` with the given `options` (see CSV.open), reads the
2079
- # source (see CSV#read), and returns the result, which will be either an Array
2080
- # of Arrays or a CSV::Table.
2081
- #
2082
- # Without headers:
2083
- # string = "foo,0\nbar,1\nbaz,2\n"
2084
- # path = 't.csv'
2085
- # File.write(path, string)
2086
- # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
2087
- #
2088
- # With headers:
2089
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2090
- # path = 't.csv'
2091
- # File.write(path, string)
2092
- # CSV.read(path, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
2093
- #
2094
- def self.read: (String | IO path, headers: true | :first_row | Array[untyped] | String, **untyped options) -> ::CSV::Table[CSV::Row]
2095
- | (String | IO path, ?::Hash[Symbol, untyped] options) -> ::Array[::Array[String?]]
2096
-
2097
- # <!--
2098
- # rdoc-file=lib/csv.rb
2099
- # - csv << row -> self
2100
- # -->
2101
- # Appends a row to `self`.
2102
- #
2103
- # * Argument `row` must be an Array object or a CSV::Row object.
2104
- # * The output stream must be open for writing.
2105
- #
2106
- # ---
2107
- #
2108
- # Append Arrays:
2109
- # CSV.generate do |csv|
2110
- # csv << ['foo', 0]
2111
- # csv << ['bar', 1]
2112
- # csv << ['baz', 2]
2113
- # end # => "foo,0\nbar,1\nbaz,2\n"
2114
- #
2115
- # Append CSV::Rows:
2116
- # headers = []
2117
- # CSV.generate do |csv|
2118
- # csv << CSV::Row.new(headers, ['foo', 0])
2119
- # csv << CSV::Row.new(headers, ['bar', 1])
2120
- # csv << CSV::Row.new(headers, ['baz', 2])
2121
- # end # => "foo,0\nbar,1\nbaz,2\n"
2122
- #
2123
- # Headers in CSV::Row objects are not appended:
2124
- # headers = ['Name', 'Count']
2125
- # CSV.generate do |csv|
2126
- # csv << CSV::Row.new(headers, ['foo', 0])
2127
- # csv << CSV::Row.new(headers, ['bar', 1])
2128
- # csv << CSV::Row.new(headers, ['baz', 2])
2129
- # end # => "foo,0\nbar,1\nbaz,2\n"
2130
- #
2131
- # ---
2132
- #
2133
- # Raises an exception if `row` is not an Array or CSV::Row:
2134
- # CSV.generate do |csv|
2135
- # # Raises NoMethodError (undefined method `collect' for :foo:Symbol)
2136
- # csv << :foo
2137
- # end
2138
- #
2139
- # Raises an exception if the output stream is not opened for writing:
2140
- # path = 't.csv'
2141
- # File.write(path, '')
2142
- # File.open(path) do |file|
2143
- # CSV.open(file) do |csv|
2144
- # # Raises IOError (not opened for writing)
2145
- # csv << ['foo', 0]
2146
- # end
2147
- # end
2148
- #
2149
- def <<: (::Array[untyped] | CSV::Row row) -> void
2150
-
2151
- # <!--
2152
- # rdoc-file=lib/csv.rb
2153
- # - generate(csv_string, **options) {|csv| ... }
2154
- # - generate(**options) {|csv| ... }
2155
- # -->
2156
- # * Argument `csv_string`, if given, must be a String object; defaults to a
2157
- # new empty String.
2158
- # * Arguments `options`, if given, should be generating options. See [Options
2159
- # for Generating](#class-CSV-label-Options+for+Generating).
2160
- #
2161
- # ---
2162
- #
2163
- # Creates a new CSV object via `CSV.new(csv_string, **options)`; calls the block
2164
- # with the CSV object, which the block may modify; returns the String generated
2165
- # from the CSV object.
2166
- #
2167
- # Note that a passed String **is** modified by this method. Pass
2168
- # `csv_string`.dup if the String must be preserved.
2169
- #
2170
- # This method has one additional option: `:encoding`, which sets the base
2171
- # Encoding for the output if no no `str` is specified. CSV needs this hint if
2172
- # you plan to output non-ASCII compatible data.
2173
- #
2174
- # ---
2175
- #
2176
- # Add lines:
2177
- # input_string = "foo,0\nbar,1\nbaz,2\n"
2178
- # output_string = CSV.generate(input_string) do |csv|
2179
- # csv << ['bat', 3]
2180
- # csv << ['bam', 4]
2181
- # end
2182
- # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
2183
- # input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
2184
- # output_string.equal?(input_string) # => true # Same string, modified
2185
- #
2186
- # Add lines into new string, preserving old string:
2187
- # input_string = "foo,0\nbar,1\nbaz,2\n"
2188
- # output_string = CSV.generate(input_string.dup) do |csv|
2189
- # csv << ['bat', 3]
2190
- # csv << ['bam', 4]
2191
- # end
2192
- # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
2193
- # input_string # => "foo,0\nbar,1\nbaz,2\n"
2194
- # output_string.equal?(input_string) # => false # Different strings
2195
- #
2196
- # Create lines from nothing:
2197
- # output_string = CSV.generate do |csv|
2198
- # csv << ['foo', 0]
2199
- # csv << ['bar', 1]
2200
- # csv << ['baz', 2]
2201
- # end
2202
- # output_string # => "foo,0\nbar,1\nbaz,2\n"
2203
- #
2204
- # ---
2205
- #
2206
- # Raises an exception if `csv_string` is not a String object:
2207
- # # Raises TypeError (no implicit conversion of Integer into String)
2208
- # CSV.generate(0)
2209
- #
2210
- def self.generate: (?String str, **untyped options) { (CSV csv) -> void } -> String
2211
-
2212
- # <!--
2213
- # rdoc-file=lib/csv.rb
2214
- # - csv.each -> enumerator
2215
- # - csv.each {|row| ...}
2216
- # -->
2217
- # Calls the block with each successive row. The data source must be opened for
2218
- # reading.
2219
- #
2220
- # Without headers:
2221
- # string = "foo,0\nbar,1\nbaz,2\n"
2222
- # csv = CSV.new(string)
2223
- # csv.each do |row|
2224
- # p row
2225
- # end
2226
- #
2227
- # Output:
2228
- # ["foo", "0"]
2229
- # ["bar", "1"]
2230
- # ["baz", "2"]
2231
- #
2232
- # With headers:
2233
- # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2234
- # csv = CSV.new(string, headers: true)
2235
- # csv.each do |row|
2236
- # p row
2237
- # end
2238
- #
2239
- # Output:
2240
- # <CSV::Row "Name":"foo" "Value":"0">
2241
- # <CSV::Row "Name":"bar" "Value":"1">
2242
- # <CSV::Row "Name":"baz" "Value":"2">
2243
- #
2244
- # ---
2245
- #
2246
- # Raises an exception if the source is not opened for reading:
2247
- # string = "foo,0\nbar,1\nbaz,2\n"
2248
- # csv = CSV.new(string)
2249
- # csv.close
2250
- # # Raises IOError (not opened for reading)
2251
- # csv.each do |row|
2252
- # p row
2253
- # end
2254
- #
2255
- def each: () -> Enumerator[untyped, Integer]
2256
- | () { (untyped) -> void } -> Integer
2257
-
2258
- # <!--
2259
- # rdoc-file=lib/csv.rb
2260
- # - csv.headers -> object
2261
- # -->
2262
- # Returns the value that determines whether headers are used; used for parsing;
2263
- # see {Option `headers`[}](#class-CSV-label-Option+headers):
2264
- # CSV.new('').headers # => nil
2265
- #
2266
- def headers: () -> (Array[String] | true | nil)
2267
- end
2268
-
2269
- # <!-- rdoc-file=lib/csv.rb -->
2270
- # Default values for method options.
2271
- #
2272
- CSV::DEFAULT_OPTIONS: ::Hash[untyped, untyped]
2273
-
2274
- # <!-- rdoc-file=lib/csv/version.rb -->
2275
- # The version of the installed library.
2276
- #
2277
- CSV::VERSION: String
2278
-
2279
- # <!-- rdoc-file=lib/csv/row.rb -->
2280
- # # CSV::Row
2281
- # A CSV::Row instance represents a CSV table row. (see [class
2282
- # CSV](../CSV.html)).
2283
- #
2284
- # The instance may have:
2285
- # * Fields: each is an object, not necessarily a String.
2286
- # * Headers: each serves a key, and also need not be a String.
2287
- #
2288
- # ### Instance Methods
2289
- #
2290
- # CSV::Row has three groups of instance methods:
2291
- # * Its own internally defined instance methods.
2292
- # * Methods included by module Enumerable.
2293
- # * Methods delegated to class Array.:
2294
- # * Array#empty?
2295
- # * Array#length
2296
- # * Array#size
2297
- #
2298
- # ## Creating a CSV::Row Instance
2299
- #
2300
- # Commonly, a new CSV::Row instance is created by parsing CSV source that has
2301
- # headers:
2302
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2303
- # table = CSV.parse(source, headers: true)
2304
- # table.each {|row| p row }
2305
- #
2306
- # Output:
2307
- # #<CSV::Row "Name":"foo" "Value":"0">
2308
- # #<CSV::Row "Name":"bar" "Value":"1">
2309
- # #<CSV::Row "Name":"baz" "Value":"2">
2310
- #
2311
- # You can also create a row directly. See ::new.
2312
- #
2313
- # ## Headers
2314
- #
2315
- # Like a CSV::Table, a CSV::Row has headers.
2316
- #
2317
- # A CSV::Row that was created by parsing CSV source inherits its headers from
2318
- # the table:
2319
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2320
- # table = CSV.parse(source, headers: true)
2321
- # row = table.first
2322
- # row.headers # => ["Name", "Value"]
2323
- #
2324
- # You can also create a new row with headers; like the keys in a Hash, the
2325
- # headers need not be Strings:
2326
- # row = CSV::Row.new([:name, :value], ['foo', 0])
2327
- # row.headers # => [:name, :value]
2328
- #
2329
- # The new row retains its headers even if added to a table that has headers:
2330
- # table << row # => #<CSV::Table mode:col_or_row row_count:5>
2331
- # row.headers # => [:name, :value]
2332
- # row[:name] # => "foo"
2333
- # row['Name'] # => nil
2334
- #
2335
- # ## Accessing Fields
2336
- #
2337
- # You may access a field in a CSV::Row with either its Integer index
2338
- # (Array-style) or its header (Hash-style).
2339
- #
2340
- # Fetch a field using method #[]:
2341
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
2342
- # row[1] # => 0
2343
- # row['Value'] # => 0
2344
- #
2345
- # Set a field using method #[]=:
2346
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
2347
- # row # => #<CSV::Row "Name":"foo" "Value":0>
2348
- # row[0] = 'bar'
2349
- # row['Value'] = 1
2350
- # row # => #<CSV::Row "Name":"bar" "Value":1>
2351
- #
2352
- class CSV::Row < Object
2353
- include Enumerable[Array[String]]
2354
- extend Forwardable
2355
-
2356
- # <!--
2357
- # rdoc-file=lib/csv/row.rb
2358
- # - CSV::Row.new(headers, fields, header_row = false) -> csv_row
2359
- # -->
2360
- # Returns the new CSV::Row instance constructed from arguments `headers` and
2361
- # `fields`; both should be Arrays; note that the fields need not be Strings:
2362
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0])
2363
- # row # => #<CSV::Row "Name":"foo" "Value":0>
2364
- #
2365
- # If the Array lengths are different, the shorter is `nil`-filled:
2366
- # row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0])
2367
- # row # => #<CSV::Row "Name":"foo" "Value":0 "Date":nil "Size":nil>
2368
- #
2369
- # Each CSV::Row object is either a *field row* or a *header row*; by default, a
2370
- # new row is a field row; for the row created above:
2371
- # row.field_row? # => true
2372
- # row.header_row? # => false
2373
- #
2374
- # If the optional argument `header_row` is given as `true`, the created row is a
2375
- # header row:
2376
- # row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true)
2377
- # row # => #<CSV::Row "Name":"foo" "Value":0>
2378
- # row.field_row? # => false
2379
- # row.header_row? # => true
2380
- #
2381
- def initialize: (Array[untyped] headers, Array[untyped] fields, ?header_row: bool) -> void
2382
-
2383
- # <!--
2384
- # rdoc-file=lib/csv/row.rb
2385
- # - row << [header, value] -> self
2386
- # - row << hash -> self
2387
- # - row << value -> self
2388
- # -->
2389
- # Adds a field to `self`; returns `self`:
2390
- #
2391
- # If the argument is a 2-element Array `[header, value]`, a field is added with
2392
- # the given `header` and `value`:
2393
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2394
- # table = CSV.parse(source, headers: true)
2395
- # row = table[0]
2396
- # row << ['NAME', 'Bat']
2397
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
2398
- #
2399
- # If the argument is a Hash, each `key-value` pair is added as a field with
2400
- # header `key` and value `value`.
2401
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2402
- # table = CSV.parse(source, headers: true)
2403
- # row = table[0]
2404
- # row << {NAME: 'Bat', name: 'Bam'}
2405
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
2406
- #
2407
- # Otherwise, the given `value` is added as a field with no header.
2408
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2409
- # table = CSV.parse(source, headers: true)
2410
- # row = table[0]
2411
- # row << 'Bag'
2412
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
2413
- #
2414
- def <<: (untyped arg) -> untyped
2415
-
2416
- # <!--
2417
- # rdoc-file=lib/csv/row.rb
2418
- # - row == other -> true or false
2419
- # -->
2420
- # Returns `true` if `other` is a /CSV::Row that has the same fields (headers and
2421
- # values) in the same order as `self`; otherwise returns `false`:
2422
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2423
- # table = CSV.parse(source, headers: true)
2424
- # row = table[0]
2425
- # other_row = table[0]
2426
- # row == other_row # => true
2427
- # other_row = table[1]
2428
- # row == other_row # => false
2429
- #
2430
- def ==: (untyped other) -> bool
2431
-
2432
- # <!--
2433
- # rdoc-file=lib/csv/row.rb
2434
- # - [](header_or_index, minimum_index = 0)
2435
- # -->
2436
- #
2437
- alias [] field
2438
-
2439
- # <!--
2440
- # rdoc-file=lib/csv/row.rb
2441
- # - row[index] = value -> value
2442
- # - row[header, offset] = value -> value
2443
- # - row[header] = value -> value
2444
- # -->
2445
- # Assigns the field value for the given `index` or `header`; returns `value`.
2446
- #
2447
- # ---
2448
- #
2449
- # Assign field value by Integer index:
2450
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2451
- # table = CSV.parse(source, headers: true)
2452
- # row = table[0]
2453
- # row[0] = 'Bat'
2454
- # row[1] = 3
2455
- # row # => #<CSV::Row "Name":"Bat" "Value":3>
2456
- #
2457
- # Counts backward from the last column if `index` is negative:
2458
- # row[-1] = 4
2459
- # row[-2] = 'Bam'
2460
- # row # => #<CSV::Row "Name":"Bam" "Value":4>
2461
- #
2462
- # Extends the row with `nil:nil` if positive `index` is not in the row:
2463
- # row[4] = 5
2464
- # row # => #<CSV::Row "Name":"bad" "Value":4 nil:nil nil:nil nil:5>
2465
- #
2466
- # Raises IndexError if negative `index` is too small (too far from zero).
2467
- #
2468
- # ---
2469
- #
2470
- # Assign field value by header (first found):
2471
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2472
- # table = CSV.parse(source, headers: true)
2473
- # row = table[0]
2474
- # row['Name'] = 'Bat'
2475
- # row # => #<CSV::Row "Name":"Bat" "Name":"Bar" "Name":"Baz">
2476
- #
2477
- # Assign field value by header, ignoring `offset` leading fields:
2478
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2479
- # table = CSV.parse(source, headers: true)
2480
- # row = table[0]
2481
- # row['Name', 2] = 4
2482
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":4>
2483
- #
2484
- # Append new field by (new) header:
2485
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2486
- # table = CSV.parse(source, headers: true)
2487
- # row = table[0]
2488
- # row['New'] = 6
2489
- # row# => #<CSV::Row "Name":"foo" "Value":"0" "New":6>
2490
- #
2491
- def []=: (*untyped args) -> untyped
2492
-
2493
- # <!--
2494
- # rdoc-file=lib/csv/row.rb
2495
- # - delete(index) -> [header, value] or nil
2496
- # - delete(header) -> [header, value] or empty_array
2497
- # - delete(header, offset) -> [header, value] or empty_array
2498
- # -->
2499
- # Removes a specified field from `self`; returns the 2-element Array `[header,
2500
- # value]` if the field exists.
2501
- #
2502
- # If an Integer argument `index` is given, removes and returns the field at
2503
- # offset `index`, or returns `nil` if the field does not exist:
2504
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2505
- # table = CSV.parse(source, headers: true)
2506
- # row = table[0]
2507
- # row.delete(1) # => ["Name", "Bar"]
2508
- # row.delete(50) # => nil
2509
- #
2510
- # Otherwise, if the single argument `header` is given, removes and returns the
2511
- # first-found field with the given header, of returns a new empty Array if the
2512
- # field does not exist:
2513
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2514
- # table = CSV.parse(source, headers: true)
2515
- # row = table[0]
2516
- # row.delete('Name') # => ["Name", "Foo"]
2517
- # row.delete('NAME') # => []
2518
- #
2519
- # If argument `header` and Integer argument `offset` are given, removes and
2520
- # returns the first-found field with the given header whose `index` is at least
2521
- # as large as `offset`:
2522
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2523
- # table = CSV.parse(source, headers: true)
2524
- # row = table[0]
2525
- # row.delete('Name', 1) # => ["Name", "Bar"]
2526
- # row.delete('NAME', 1) # => []
2527
- #
2528
- def delete: (untyped header_or_index, ?untyped minimum_index) -> untyped
2529
-
2530
- # <!--
2531
- # rdoc-file=lib/csv/row.rb
2532
- # - row.delete_if {|header, value| ... } -> self
2533
- # -->
2534
- # Removes fields from `self` as selected by the block; returns `self`.
2535
- #
2536
- # Removes each field for which the block returns a truthy value:
2537
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2538
- # table = CSV.parse(source, headers: true)
2539
- # row = table[0]
2540
- # row.delete_if {|header, value| value.start_with?('B') } # => true
2541
- # row # => #<CSV::Row "Name":"Foo">
2542
- # row.delete_if {|header, value| header.start_with?('B') } # => false
2543
- #
2544
- # If no block is given, returns a new Enumerator:
2545
- # row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
2546
- #
2547
- def delete_if: () { (*untyped) -> untyped } -> untyped
2548
-
2549
- # <!--
2550
- # rdoc-file=lib/csv/row.rb
2551
- # - row.dig(index_or_header, *identifiers) -> object
2552
- # -->
2553
- # Finds and returns the object in nested object that is specified by
2554
- # `index_or_header` and `specifiers`.
2555
- #
2556
- # The nested objects may be instances of various classes. See [Dig
2557
- # Methods](rdoc-ref:dig_methods.rdoc).
2558
- #
2559
- # Examples:
2560
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2561
- # table = CSV.parse(source, headers: true)
2562
- # row = table[0]
2563
- # row.dig(1) # => "0"
2564
- # row.dig('Value') # => "0"
2565
- # row.dig(5) # => nil
2566
- #
2567
- def dig: (untyped index_or_header, *untyped indexes) -> untyped
2568
-
2569
- # <!--
2570
- # rdoc-file=lib/csv/row.rb
2571
- # - row.each {|header, value| ... } -> self
2572
- # -->
2573
- # Calls the block with each header-value pair; returns `self`:
2574
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2575
- # table = CSV.parse(source, headers: true)
2576
- # row = table[0]
2577
- # row.each {|header, value| p [header, value] }
2578
- #
2579
- # Output:
2580
- # ["Name", "Foo"]
2581
- # ["Name", "Bar"]
2582
- # ["Name", "Baz"]
2583
- #
2584
- # If no block is given, returns a new Enumerator:
2585
- # row.each # => #<Enumerator: #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz">:each>
2586
- #
2587
- def each: () -> Enumerator[Array[String], self]
2588
- | () { (Array[String]) -> void } -> self
2589
-
2590
- # <!--
2591
- # rdoc-file=lib/csv/row.rb
2592
- # - each_pair(&block)
2593
- # -->
2594
- #
2595
- alias each_pair each
2596
-
2597
- def empty?: (*untyped args) { (*untyped) -> untyped } -> bool
2598
-
2599
- # <!--
2600
- # rdoc-file=lib/csv/row.rb
2601
- # - fetch(header) -> value
2602
- # - fetch(header, default) -> value
2603
- # - fetch(header) {|row| ... } -> value
2604
- # -->
2605
- # Returns the field value as specified by `header`.
2606
- #
2607
- # ---
2608
- #
2609
- # With the single argument `header`, returns the field value for that header
2610
- # (first found):
2611
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2612
- # table = CSV.parse(source, headers: true)
2613
- # row = table[0]
2614
- # row.fetch('Name') # => "Foo"
2615
- #
2616
- # Raises exception `KeyError` if the header does not exist.
2617
- #
2618
- # ---
2619
- #
2620
- # With arguments `header` and `default` given, returns the field value for the
2621
- # header (first found) if the header exists, otherwise returns `default`:
2622
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2623
- # table = CSV.parse(source, headers: true)
2624
- # row = table[0]
2625
- # row.fetch('Name', '') # => "Foo"
2626
- # row.fetch(:nosuch, '') # => ""
2627
- #
2628
- # ---
2629
- #
2630
- # With argument `header` and a block given, returns the field value for the
2631
- # header (first found) if the header exists; otherwise calls the block and
2632
- # returns its return value:
2633
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2634
- # table = CSV.parse(source, headers: true)
2635
- # row = table[0]
2636
- # row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo"
2637
- # row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'"
2638
- #
2639
- def fetch: (untyped header, *untyped varargs) ?{ (*untyped) -> untyped } -> untyped
2640
-
2641
- # <!--
2642
- # rdoc-file=lib/csv/row.rb
2643
- # - field(index) -> value
2644
- # - field(header) -> value
2645
- # - field(header, offset) -> value
2646
- # -->
2647
- # Returns the field value for the given `index` or `header`.
2648
- #
2649
- # ---
2650
- #
2651
- # Fetch field value by Integer index:
2652
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2653
- # table = CSV.parse(source, headers: true)
2654
- # row = table[0]
2655
- # row.field(0) # => "foo"
2656
- # row.field(1) # => "bar"
2657
- #
2658
- # Counts backward from the last column if `index` is negative:
2659
- # row.field(-1) # => "0"
2660
- # row.field(-2) # => "foo"
2661
- #
2662
- # Returns `nil` if `index` is out of range:
2663
- # row.field(2) # => nil
2664
- # row.field(-3) # => nil
2665
- #
2666
- # ---
2667
- #
2668
- # Fetch field value by header (first found):
2669
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2670
- # table = CSV.parse(source, headers: true)
2671
- # row = table[0]
2672
- # row.field('Name') # => "Foo"
2673
- #
2674
- # Fetch field value by header, ignoring `offset` leading fields:
2675
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2676
- # table = CSV.parse(source, headers: true)
2677
- # row = table[0]
2678
- # row.field('Name', 2) # => "Baz"
2679
- #
2680
- # Returns `nil` if the header does not exist.
2681
- #
2682
- def field: (untyped header_or_index, ?untyped minimum_index) -> untyped
2683
-
2684
- # <!--
2685
- # rdoc-file=lib/csv/row.rb
2686
- # - row.field?(value) -> true or false
2687
- # -->
2688
- # Returns `true` if `value` is a field in this row, `false` otherwise:
2689
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2690
- # table = CSV.parse(source, headers: true)
2691
- # row = table[0]
2692
- # row.field?('Bar') # => true
2693
- # row.field?('BAR') # => false
2694
- #
2695
- def field?: (untyped data) -> bool
2696
-
2697
- # <!--
2698
- # rdoc-file=lib/csv/row.rb
2699
- # - row.field_row? -> true or false
2700
- # -->
2701
- # Returns `true` if this is a field row, `false` otherwise.
2702
- #
2703
- def field_row?: () -> bool
2704
-
2705
- # <!--
2706
- # rdoc-file=lib/csv/row.rb
2707
- # - self.fields(*specifiers) -> array_of_fields
2708
- # -->
2709
- # Returns field values per the given `specifiers`, which may be any mixture of:
2710
- # * Integer index.
2711
- # * Range of Integer indexes.
2712
- # * 2-element Array containing a header and offset.
2713
- # * Header.
2714
- # * Range of headers.
2715
- #
2716
- # For `specifier` in one of the first four cases above, returns the result of
2717
- # `self.field(specifier)`; see #field.
2718
- #
2719
- # Although there may be any number of `specifiers`, the examples here will
2720
- # illustrate one at a time.
2721
- #
2722
- # When the specifier is an Integer `index`, returns `self.field(index)`L
2723
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2724
- # table = CSV.parse(source, headers: true)
2725
- # row = table[0]
2726
- # row.fields(1) # => ["Bar"]
2727
- #
2728
- # When the specifier is a Range of Integers `range`, returns
2729
- # `self.field(range)`:
2730
- # row.fields(1..2) # => ["Bar", "Baz"]
2731
- #
2732
- # When the specifier is a 2-element Array `array`, returns `self.field(array)`L
2733
- # row.fields('Name', 1) # => ["Foo", "Bar"]
2734
- #
2735
- # When the specifier is a header `header`, returns `self.field(header)`L
2736
- # row.fields('Name') # => ["Foo"]
2737
- #
2738
- # When the specifier is a Range of headers `range`, forms a new Range
2739
- # `new_range` from the indexes of `range.start` and `range.end`, and returns
2740
- # `self.field(new_range)`:
2741
- # source = "Name,NAME,name\nFoo,Bar,Baz\n"
2742
- # table = CSV.parse(source, headers: true)
2743
- # row = table[0]
2744
- # row.fields('Name'..'NAME') # => ["Foo", "Bar"]
2745
- #
2746
- # Returns all fields if no argument given:
2747
- # row.fields # => ["Foo", "Bar", "Baz"]
2748
- #
2749
- def fields: (*untyped headers_and_or_indices) -> untyped
2750
-
2751
- # <!--
2752
- # rdoc-file=lib/csv/row.rb
2753
- # - row.has_key?(header) -> true or false
2754
- # -->
2755
- # Returns `true` if there is a field with the given `header`, `false` otherwise.
2756
- #
2757
- def has_key?: (untyped header) -> bool
2758
-
2759
- # <!--
2760
- # rdoc-file=lib/csv/row.rb
2761
- # - header?(header)
2762
- # -->
2763
- #
2764
- alias header? has_key?
2765
-
2766
- # <!--
2767
- # rdoc-file=lib/csv/row.rb
2768
- # - row.header_row? -> true or false
2769
- # -->
2770
- # Returns `true` if this is a header row, `false` otherwise.
2771
- #
2772
- def header_row?: () -> bool
2773
-
2774
- # <!--
2775
- # rdoc-file=lib/csv/row.rb
2776
- # - row.headers -> array_of_headers
2777
- # -->
2778
- # Returns the headers for this row:
2779
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2780
- # table = CSV.parse(source, headers: true)
2781
- # row = table.first
2782
- # row.headers # => ["Name", "Value"]
2783
- #
2784
- def headers: () -> untyped
2785
-
2786
- # <!--
2787
- # rdoc-file=lib/csv/row.rb
2788
- # - include?(header)
2789
- # -->
2790
- #
2791
- alias include? has_key?
2792
-
2793
- # <!--
2794
- # rdoc-file=lib/csv/row.rb
2795
- # - index(header) -> index
2796
- # - index(header, offset) -> index
2797
- # -->
2798
- # Returns the index for the given header, if it exists; otherwise returns `nil`.
2799
- #
2800
- # With the single argument `header`, returns the index of the first-found field
2801
- # with the given `header`:
2802
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2803
- # table = CSV.parse(source, headers: true)
2804
- # row = table[0]
2805
- # row.index('Name') # => 0
2806
- # row.index('NAME') # => nil
2807
- #
2808
- # With arguments `header` and `offset`, returns the index of the first-found
2809
- # field with given `header`, but ignoring the first `offset` fields:
2810
- # row.index('Name', 1) # => 1
2811
- # row.index('Name', 3) # => nil
2812
- #
2813
- def index: (untyped header, ?untyped minimum_index) -> untyped
2814
-
2815
- # <!--
2816
- # rdoc-file=lib/csv/row.rb
2817
- # - row.inspect -> string
2818
- # -->
2819
- # Returns an ASCII-compatible String showing:
2820
- # * Class CSV::Row.
2821
- # * Header-value pairs.
2822
- # Example:
2823
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2824
- # table = CSV.parse(source, headers: true)
2825
- # row = table[0]
2826
- # row.inspect # => "#<CSV::Row \"Name\":\"foo\" \"Value\":\"0\">"
2827
- #
2828
- def inspect: () -> String
2829
-
2830
- # <!--
2831
- # rdoc-file=lib/csv/row.rb
2832
- # - key?(header)
2833
- # -->
2834
- #
2835
- alias key? has_key?
2836
-
2837
- def length: (*untyped args) { (*untyped) -> untyped } -> untyped
2838
-
2839
- # <!--
2840
- # rdoc-file=lib/csv/row.rb
2841
- # - member?(header)
2842
- # -->
2843
- #
2844
- alias member? has_key?
2845
-
2846
- # <!--
2847
- # rdoc-file=lib/csv/row.rb
2848
- # - row.push(*values) -> self
2849
- # -->
2850
- # Appends each of the given `values` to `self` as a field; returns `self`:
2851
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2852
- # table = CSV.parse(source, headers: true)
2853
- # row = table[0]
2854
- # row.push('Bat', 'Bam')
2855
- # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
2856
- #
2857
- def push: (*untyped args) -> untyped
2858
-
2859
- def size: (*untyped args) { (*untyped) -> untyped } -> untyped
2860
-
2861
- # <!--
2862
- # rdoc-file=lib/csv/row.rb
2863
- # - row.to_csv -> csv_string
2864
- # -->
2865
- # Returns the row as a CSV String. Headers are not included:
2866
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2867
- # table = CSV.parse(source, headers: true)
2868
- # row = table[0]
2869
- # row.to_csv # => "foo,0\n"
2870
- #
2871
- def to_csv: (**untyped) -> untyped
2872
-
2873
- # <!--
2874
- # rdoc-file=lib/csv/row.rb
2875
- # - row.to_h -> hash
2876
- # -->
2877
- # Returns the new Hash formed by adding each header-value pair in `self` as a
2878
- # key-value pair in the Hash.
2879
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2880
- # table = CSV.parse(source, headers: true)
2881
- # row = table[0]
2882
- # row.to_h # => {"Name"=>"foo", "Value"=>"0"}
2883
- #
2884
- # Header order is preserved, but repeated headers are ignored:
2885
- # source = "Name,Name,Name\nFoo,Bar,Baz\n"
2886
- # table = CSV.parse(source, headers: true)
2887
- # row = table[0]
2888
- # row.to_h # => {"Name"=>"Foo"}
2889
- #
2890
- def to_h: () -> untyped
2891
-
2892
- # <!--
2893
- # rdoc-file=lib/csv/row.rb
2894
- # - to_hash()
2895
- # -->
2896
- #
2897
- alias to_hash to_h
2898
-
2899
- # <!--
2900
- # rdoc-file=lib/csv/row.rb
2901
- # - to_s(**options)
2902
- # -->
2903
- #
2904
- alias to_s to_csv
2905
-
2906
- # <!--
2907
- # rdoc-file=lib/csv/row.rb
2908
- # - values_at(*headers_and_or_indices)
2909
- # -->
2910
- #
2911
- alias values_at fields
2912
- end
2913
-
2914
- class CSV::FieldInfo < Struct[untyped]
2915
- end
2916
-
2917
- # <!-- rdoc-file=lib/csv.rb -->
2918
- # The error thrown when the parser encounters illegal CSV formatting.
2919
- #
2920
- class CSV::MalformedCSVError < RuntimeError
2921
- end
2922
-
2923
- # <!-- rdoc-file=lib/csv/table.rb -->
2924
- # # CSV::Table
2925
- # A CSV::Table instance represents CSV data. (see [class CSV](../CSV.html)).
2926
- #
2927
- # The instance may have:
2928
- # * Rows: each is a Table::Row object.
2929
- # * Headers: names for the columns.
2930
- #
2931
- # ### Instance Methods
2932
- #
2933
- # CSV::Table has three groups of instance methods:
2934
- # * Its own internally defined instance methods.
2935
- # * Methods included by module Enumerable.
2936
- # * Methods delegated to class Array.:
2937
- # * Array#empty?
2938
- # * Array#length
2939
- # * Array#size
2940
- #
2941
- # ## Creating a CSV::Table Instance
2942
- #
2943
- # Commonly, a new CSV::Table instance is created by parsing CSV source using
2944
- # headers:
2945
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2946
- # table = CSV.parse(source, headers: true)
2947
- # table.class # => CSV::Table
2948
- #
2949
- # You can also create an instance directly. See ::new.
2950
- #
2951
- # ## Headers
2952
- #
2953
- # If a table has headers, the headers serve as labels for the columns of data.
2954
- # Each header serves as the label for its column.
2955
- #
2956
- # The headers for a CSV::Table object are stored as an Array of Strings.
2957
- #
2958
- # Commonly, headers are defined in the first row of CSV source:
2959
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2960
- # table = CSV.parse(source, headers: true)
2961
- # table.headers # => ["Name", "Value"]
2962
- #
2963
- # If no headers are defined, the Array is empty:
2964
- # table = CSV::Table.new([])
2965
- # table.headers # => []
2966
- #
2967
- # ## Access Modes
2968
- #
2969
- # CSV::Table provides three modes for accessing table data:
2970
- # * Row mode.
2971
- # * Column mode.
2972
- # * Mixed mode (the default for a new table).
2973
- #
2974
- # The access mode for aCSV::Table instance affects the behavior of some of its
2975
- # instance methods:
2976
- # * #[]
2977
- # * #[]=
2978
- # * #delete
2979
- # * #delete_if
2980
- # * #each
2981
- # * #values_at
2982
- #
2983
- # ### Row Mode
2984
- #
2985
- # Set a table to row mode with method #by_row!:
2986
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
2987
- # table = CSV.parse(source, headers: true)
2988
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
2989
- #
2990
- # Specify a single row by an Integer index:
2991
- # # Get a row.
2992
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
2993
- # # Set a row, then get it.
2994
- # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
2995
- # table[1] # => #<CSV::Row "Name":"bam" "Value":3>
2996
- #
2997
- # Specify a sequence of rows by a Range:
2998
- # # Get rows.
2999
- # table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
3000
- # # Set rows, then get them.
3001
- # table[1..2] = [
3002
- # CSV::Row.new(['Name', 'Value'], ['bat', 4]),
3003
- # CSV::Row.new(['Name', 'Value'], ['bad', 5]),
3004
- # ]
3005
- # table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
3006
- #
3007
- # ### Column Mode
3008
- #
3009
- # Set a table to column mode with method #by_col!:
3010
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3011
- # table = CSV.parse(source, headers: true)
3012
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3013
- #
3014
- # Specify a column by an Integer index:
3015
- # # Get a column.
3016
- # table[0]
3017
- # # Set a column, then get it.
3018
- # table[0] = ['FOO', 'BAR', 'BAZ']
3019
- # table[0] # => ["FOO", "BAR", "BAZ"]
3020
- #
3021
- # Specify a column by its String header:
3022
- # # Get a column.
3023
- # table['Name'] # => ["FOO", "BAR", "BAZ"]
3024
- # # Set a column, then get it.
3025
- # table['Name'] = ['Foo', 'Bar', 'Baz']
3026
- # table['Name'] # => ["Foo", "Bar", "Baz"]
3027
- #
3028
- # ### Mixed Mode
3029
- #
3030
- # In mixed mode, you can refer to either rows or columns:
3031
- # * An Integer index refers to a row.
3032
- # * A Range index refers to multiple rows.
3033
- # * A String index refers to a column.
3034
- #
3035
- # Set a table to mixed mode with method #by_col_or_row!:
3036
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3037
- # table = CSV.parse(source, headers: true)
3038
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
3039
- #
3040
- # Specify a single row by an Integer index:
3041
- # # Get a row.
3042
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
3043
- # # Set a row, then get it.
3044
- # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
3045
- # table[1] # => #<CSV::Row "Name":"bam" "Value":3>
3046
- #
3047
- # Specify a sequence of rows by a Range:
3048
- # # Get rows.
3049
- # table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
3050
- # # Set rows, then get them.
3051
- # table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4])
3052
- # table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5])
3053
- # table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
3054
- #
3055
- # Specify a column by its String header:
3056
- # # Get a column.
3057
- # table['Name'] # => ["foo", "bat", "bad"]
3058
- # # Set a column, then get it.
3059
- # table['Name'] = ['Foo', 'Bar', 'Baz']
3060
- # table['Name'] # => ["Foo", "Bar", "Baz"]
3061
- #
3062
- class CSV::Table[out Elem] < Object
3063
- include Enumerable[Elem]
3064
- extend Forwardable
3065
-
3066
- # <!--
3067
- # rdoc-file=lib/csv/table.rb
3068
- # - CSV::Table.new(array_of_rows, headers = nil) -> csv_table
3069
- # -->
3070
- # Returns a new CSV::Table object.
3071
- #
3072
- # * Argument `array_of_rows` must be an Array of CSV::Row objects.
3073
- # * Argument `headers`, if given, may be an Array of Strings.
3074
- #
3075
- # ---
3076
- #
3077
- # Create an empty CSV::Table object:
3078
- # table = CSV::Table.new([])
3079
- # table # => #<CSV::Table mode:col_or_row row_count:1>
3080
- #
3081
- # Create a non-empty CSV::Table object:
3082
- # rows = [
3083
- # CSV::Row.new([], []),
3084
- # CSV::Row.new([], []),
3085
- # CSV::Row.new([], []),
3086
- # ]
3087
- # table = CSV::Table.new(rows)
3088
- # table # => #<CSV::Table mode:col_or_row row_count:4>
3089
- #
3090
- # ---
3091
- #
3092
- # If argument `headers` is an Array of Strings, those Strings become the table's
3093
- # headers:
3094
- # table = CSV::Table.new([], headers: ['Name', 'Age'])
3095
- # table.headers # => ["Name", "Age"]
3096
- #
3097
- # If argument `headers` is not given and the table has rows, the headers are
3098
- # taken from the first row:
3099
- # rows = [
3100
- # CSV::Row.new(['Foo', 'Bar'], []),
3101
- # CSV::Row.new(['foo', 'bar'], []),
3102
- # CSV::Row.new(['FOO', 'BAR'], []),
3103
- # ]
3104
- # table = CSV::Table.new(rows)
3105
- # table.headers # => ["Foo", "Bar"]
3106
- #
3107
- # If argument `headers` is not given and the table is empty (has no rows), the
3108
- # headers are also empty:
3109
- # table = CSV::Table.new([])
3110
- # table.headers # => []
3111
- #
3112
- # ---
3113
- #
3114
- # Raises an exception if argument `array_of_rows` is not an Array object:
3115
- # # Raises NoMethodError (undefined method `first' for :foo:Symbol):
3116
- # CSV::Table.new(:foo)
3117
- #
3118
- # Raises an exception if an element of `array_of_rows` is not a CSV::Table
3119
- # object:
3120
- # # Raises NoMethodError (undefined method `headers' for :foo:Symbol):
3121
- # CSV::Table.new([:foo])
3122
- #
3123
- def initialize: (untyped array_of_rows, ?headers: untyped) -> untyped
3124
-
3125
- # <!--
3126
- # rdoc-file=lib/csv/table.rb
3127
- # - table << row_or_array -> self
3128
- # -->
3129
- # If `row_or_array` is a CSV::Row object, it is appended to the table:
3130
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3131
- # table = CSV.parse(source, headers: true)
3132
- # table << CSV::Row.new(table.headers, ['bat', 3])
3133
- # table[3] # => #<CSV::Row "Name":"bat" "Value":3>
3134
- #
3135
- # If `row_or_array` is an Array, it is used to create a new CSV::Row object
3136
- # which is then appended to the table:
3137
- # table << ['bam', 4]
3138
- # table[4] # => #<CSV::Row "Name":"bam" "Value":4>
3139
- #
3140
- def <<: (untyped row_or_array) -> untyped
3141
-
3142
- # <!--
3143
- # rdoc-file=lib/csv/table.rb
3144
- # - table == other_table -> true or false
3145
- # -->
3146
- # Returns `true` if all each row of `self` `==` the corresponding row of
3147
- # `other_table`, otherwise, `false`.
3148
- #
3149
- # The access mode does no affect the result.
3150
- #
3151
- # Equal tables:
3152
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3153
- # table = CSV.parse(source, headers: true)
3154
- # other_table = CSV.parse(source, headers: true)
3155
- # table == other_table # => true
3156
- #
3157
- # Different row count:
3158
- # other_table.delete(2)
3159
- # table == other_table # => false
3160
- #
3161
- # Different last row:
3162
- # other_table << ['bat', 3]
3163
- # table == other_table # => false
3164
- #
3165
- def ==: (untyped other) -> bool
3166
-
3167
- # <!--
3168
- # rdoc-file=lib/csv/table.rb
3169
- # - table[n] -> row or column_data
3170
- # - table[range] -> array_of_rows or array_of_column_data
3171
- # - table[header] -> array_of_column_data
3172
- # -->
3173
- # Returns data from the table; does not modify the table.
3174
- #
3175
- # ---
3176
- #
3177
- #
3178
- # Fetch a Row by Its Integer Index
3179
- # :
3180
- # * Form: `table[n]`, `n` an integer.
3181
- # * Access mode: `:row` or `:col_or_row`.
3182
- # * Return value: *nth* row of the table, if that row exists; otherwise `nil`.
3183
- #
3184
- # Returns the *nth* row of the table if that row exists:
3185
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3186
- # table = CSV.parse(source, headers: true)
3187
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3188
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
3189
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
3190
- # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
3191
- #
3192
- # Counts backward from the last row if `n` is negative:
3193
- # table[-1] # => #<CSV::Row "Name":"baz" "Value":"2">
3194
- #
3195
- # Returns `nil` if `n` is too large or too small:
3196
- # table[4] # => nil
3197
- # table[-4] # => nil
3198
- #
3199
- # Raises an exception if the access mode is `:row` and `n` is not an Integer:
3200
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3201
- # # Raises TypeError (no implicit conversion of String into Integer):
3202
- # table['Name']
3203
- #
3204
- # ---
3205
- #
3206
- #
3207
- # Fetch a Column by Its Integer Index
3208
- # :
3209
- # * Form: `table[n]`, `n` an Integer.
3210
- # * Access mode: `:col`.
3211
- # * Return value: *nth* column of the table, if that column exists; otherwise
3212
- # an Array of `nil` fields of length `self.size`.
3213
- #
3214
- # Returns the *nth* column of the table if that column exists:
3215
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3216
- # table = CSV.parse(source, headers: true)
3217
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3218
- # table[1] # => ["0", "1", "2"]
3219
- #
3220
- # Counts backward from the last column if `n` is negative:
3221
- # table[-2] # => ["foo", "bar", "baz"]
3222
- #
3223
- # Returns an Array of `nil` fields if `n` is too large or too small:
3224
- # table[4] # => [nil, nil, nil]
3225
- # table[-4] # => [nil, nil, nil]
3226
- #
3227
- # ---
3228
- #
3229
- #
3230
- # Fetch Rows by Range
3231
- # :
3232
- # * Form: `table[range]`, `range` a Range object.
3233
- # * Access mode: `:row` or `:col_or_row`.
3234
- # * Return value: rows from the table, beginning at row `range.start`, if
3235
- # those rows exists.
3236
- #
3237
- # Returns rows from the table, beginning at row `range.first`, if those rows
3238
- # exist:
3239
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3240
- # table = CSV.parse(source, headers: true)
3241
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3242
- # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
3243
- # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
3244
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
3245
- # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
3246
- # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
3247
- #
3248
- # If there are too few rows, returns all from `range.start` to the end:
3249
- # rows = table[1..50] # => #<CSV::Row "Name":"bar" "Value":"1">
3250
- # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
3251
- #
3252
- # Special case: if `range.start == table.size`, returns an empty Array:
3253
- # table[table.size..50] # => []
3254
- #
3255
- # If `range.end` is negative, calculates the ending index from the end:
3256
- # rows = table[0..-1]
3257
- # rows # => [#<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
3258
- #
3259
- # If `range.start` is negative, calculates the starting index from the end:
3260
- # rows = table[-1..2]
3261
- # rows # => [#<CSV::Row "Name":"baz" "Value":"2">]
3262
- #
3263
- # If `range.start` is larger than `table.size`, returns `nil`:
3264
- # table[4..4] # => nil
3265
- #
3266
- # ---
3267
- #
3268
- #
3269
- # Fetch Columns by Range
3270
- # :
3271
- # * Form: `table[range]`, `range` a Range object.
3272
- # * Access mode: `:col`.
3273
- # * Return value: column data from the table, beginning at column
3274
- # `range.start`, if those columns exist.
3275
- #
3276
- # Returns column values from the table, if the column exists; the values are
3277
- # arranged by row:
3278
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3279
- # table = CSV.parse(source, headers: true)
3280
- # table.by_col!
3281
- # table[0..1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
3282
- #
3283
- # Special case: if `range.start == headers.size`, returns an Array (size:
3284
- # `table.size`) of empty Arrays:
3285
- # table[table.headers.size..50] # => [[], [], []]
3286
- #
3287
- # If `range.end` is negative, calculates the ending index from the end:
3288
- # table[0..-1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
3289
- #
3290
- # If `range.start` is negative, calculates the starting index from the end:
3291
- # table[-2..2] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
3292
- #
3293
- # If `range.start` is larger than `table.size`, returns an Array of `nil`
3294
- # values:
3295
- # table[4..4] # => [nil, nil, nil]
3296
- #
3297
- # ---
3298
- #
3299
- #
3300
- # Fetch a Column by Its String Header
3301
- # :
3302
- # * Form: `table[header]`, `header` a String header.
3303
- # * Access mode: `:col` or `:col_or_row`
3304
- # * Return value: column data from the table, if that `header` exists.
3305
- #
3306
- # Returns column values from the table, if the column exists:
3307
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3308
- # table = CSV.parse(source, headers: true)
3309
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3310
- # table['Name'] # => ["foo", "bar", "baz"]
3311
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
3312
- # col = table['Name']
3313
- # col # => ["foo", "bar", "baz"]
3314
- #
3315
- # Modifying the returned column values does not modify the table:
3316
- # col[0] = 'bat'
3317
- # col # => ["bat", "bar", "baz"]
3318
- # table['Name'] # => ["foo", "bar", "baz"]
3319
- #
3320
- # Returns an Array of `nil` values if there is no such column:
3321
- # table['Nosuch'] # => [nil, nil, nil]
3322
- #
3323
- def []: (untyped index_or_header) -> untyped
3324
-
3325
- # <!--
3326
- # rdoc-file=lib/csv/table.rb
3327
- # - table[n] = row -> row
3328
- # - table[n] = field_or_array_of_fields -> field_or_array_of_fields
3329
- # - table[header] = field_or_array_of_fields -> field_or_array_of_fields
3330
- # -->
3331
- # Puts data onto the table.
3332
- #
3333
- # ---
3334
- #
3335
- #
3336
- # Set a Row by Its Integer Index
3337
- # :
3338
- # * Form: `table[n] = row`, `n` an Integer, `row` a CSV::Row instance or an
3339
- # Array of fields.
3340
- # * Access mode: `:row` or `:col_or_row`.
3341
- # * Return value: `row`.
3342
- #
3343
- # If the row exists, it is replaced:
3344
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3345
- # table = CSV.parse(source, headers: true)
3346
- # new_row = CSV::Row.new(['Name', 'Value'], ['bat', 3])
3347
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3348
- # return_value = table[0] = new_row
3349
- # return_value.equal?(new_row) # => true # Returned the row
3350
- # table[0].to_h # => {"Name"=>"bat", "Value"=>3}
3351
- #
3352
- # With access mode `:col_or_row`:
3353
- # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
3354
- # table[0] = CSV::Row.new(['Name', 'Value'], ['bam', 4])
3355
- # table[0].to_h # => {"Name"=>"bam", "Value"=>4}
3356
- #
3357
- # With an Array instead of a CSV::Row, inherits headers from the table:
3358
- # array = ['bad', 5]
3359
- # return_value = table[0] = array
3360
- # return_value.equal?(array) # => true # Returned the array
3361
- # table[0].to_h # => {"Name"=>"bad", "Value"=>5}
3362
- #
3363
- # If the row does not exist, extends the table by adding rows: assigns rows with
3364
- # `nil` as needed:
3365
- # table.size # => 3
3366
- # table[5] = ['bag', 6]
3367
- # table.size # => 6
3368
- # table[3] # => nil
3369
- # table[4]# => nil
3370
- # table[5].to_h # => {"Name"=>"bag", "Value"=>6}
3371
- #
3372
- # Note that the `nil` rows are actually `nil`, not a row of `nil` fields.
3373
- #
3374
- # ---
3375
- #
3376
- #
3377
- # Set a Column by Its Integer Index
3378
- # :
3379
- # * Form: `table[n] = array_of_fields`, `n` an Integer, `array_of_fields` an
3380
- # Array of String fields.
3381
- # * Access mode: `:col`.
3382
- # * Return value: `array_of_fields`.
3383
- #
3384
- # If the column exists, it is replaced:
3385
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3386
- # table = CSV.parse(source, headers: true)
3387
- # new_col = [3, 4, 5]
3388
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3389
- # return_value = table[1] = new_col
3390
- # return_value.equal?(new_col) # => true # Returned the column
3391
- # table[1] # => [3, 4, 5]
3392
- # # The rows, as revised:
3393
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3394
- # table[0].to_h # => {"Name"=>"foo", "Value"=>3}
3395
- # table[1].to_h # => {"Name"=>"bar", "Value"=>4}
3396
- # table[2].to_h # => {"Name"=>"baz", "Value"=>5}
3397
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3398
- #
3399
- # If there are too few values, fills with `nil` values:
3400
- # table[1] = [0]
3401
- # table[1] # => [0, nil, nil]
3402
- #
3403
- # If there are too many values, ignores the extra values:
3404
- # table[1] = [0, 1, 2, 3, 4]
3405
- # table[1] # => [0, 1, 2]
3406
- #
3407
- # If a single value is given, replaces all fields in the column with that value:
3408
- # table[1] = 'bat'
3409
- # table[1] # => ["bat", "bat", "bat"]
3410
- #
3411
- # ---
3412
- #
3413
- #
3414
- # Set a Column by Its String Header
3415
- # :
3416
- # * Form: `table[header] = field_or_array_of_fields`, `header` a String
3417
- # header, `field_or_array_of_fields` a field value or an Array of String
3418
- # fields.
3419
- # * Access mode: `:col` or `:col_or_row`.
3420
- # * Return value: `field_or_array_of_fields`.
3421
- #
3422
- # If the column exists, it is replaced:
3423
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3424
- # table = CSV.parse(source, headers: true)
3425
- # new_col = [3, 4, 5]
3426
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3427
- # return_value = table['Value'] = new_col
3428
- # return_value.equal?(new_col) # => true # Returned the column
3429
- # table['Value'] # => [3, 4, 5]
3430
- # # The rows, as revised:
3431
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3432
- # table[0].to_h # => {"Name"=>"foo", "Value"=>3}
3433
- # table[1].to_h # => {"Name"=>"bar", "Value"=>4}
3434
- # table[2].to_h # => {"Name"=>"baz", "Value"=>5}
3435
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3436
- #
3437
- # If there are too few values, fills with `nil` values:
3438
- # table['Value'] = [0]
3439
- # table['Value'] # => [0, nil, nil]
3440
- #
3441
- # If there are too many values, ignores the extra values:
3442
- # table['Value'] = [0, 1, 2, 3, 4]
3443
- # table['Value'] # => [0, 1, 2]
3444
- #
3445
- # If the column does not exist, extends the table by adding columns:
3446
- # table['Note'] = ['x', 'y', 'z']
3447
- # table['Note'] # => ["x", "y", "z"]
3448
- # # The rows, as revised:
3449
- # table.by_row!
3450
- # table[0].to_h # => {"Name"=>"foo", "Value"=>0, "Note"=>"x"}
3451
- # table[1].to_h # => {"Name"=>"bar", "Value"=>1, "Note"=>"y"}
3452
- # table[2].to_h # => {"Name"=>"baz", "Value"=>2, "Note"=>"z"}
3453
- # table.by_col!
3454
- #
3455
- # If a single value is given, replaces all fields in the column with that value:
3456
- # table['Value'] = 'bat'
3457
- # table['Value'] # => ["bat", "bat", "bat"]
3458
- #
3459
- def []=: (untyped index_or_header, untyped value) -> untyped
3460
-
3461
- # <!--
3462
- # rdoc-file=lib/csv/table.rb
3463
- # - table.by_col -> table_dup
3464
- # -->
3465
- # Returns a duplicate of `self`, in column mode (see [Column
3466
- # Mode](#class-CSV::Table-label-Column+Mode)):
3467
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3468
- # table = CSV.parse(source, headers: true)
3469
- # table.mode # => :col_or_row
3470
- # dup_table = table.by_col
3471
- # dup_table.mode # => :col
3472
- # dup_table.equal?(table) # => false # It's a dup
3473
- #
3474
- # This may be used to chain method calls without changing the mode (but also
3475
- # will affect performance and memory usage):
3476
- # dup_table.by_col['Name']
3477
- #
3478
- # Also note that changes to the duplicate table will not affect the original.
3479
- #
3480
- def by_col: () -> untyped
3481
-
3482
- # <!--
3483
- # rdoc-file=lib/csv/table.rb
3484
- # - table.by_col! -> self
3485
- # -->
3486
- # Sets the mode for `self` to column mode (see [Column
3487
- # Mode](#class-CSV::Table-label-Column+Mode)); returns `self`:
3488
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3489
- # table = CSV.parse(source, headers: true)
3490
- # table.mode # => :col_or_row
3491
- # table1 = table.by_col!
3492
- # table.mode # => :col
3493
- # table1.equal?(table) # => true # Returned self
3494
- #
3495
- def by_col!: () -> untyped
3496
-
3497
- # <!--
3498
- # rdoc-file=lib/csv/table.rb
3499
- # - table.by_col_or_row -> table_dup
3500
- # -->
3501
- # Returns a duplicate of `self`, in mixed mode (see [Mixed
3502
- # Mode](#class-CSV::Table-label-Mixed+Mode)):
3503
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3504
- # table = CSV.parse(source, headers: true).by_col!
3505
- # table.mode # => :col
3506
- # dup_table = table.by_col_or_row
3507
- # dup_table.mode # => :col_or_row
3508
- # dup_table.equal?(table) # => false # It's a dup
3509
- #
3510
- # This may be used to chain method calls without changing the mode (but also
3511
- # will affect performance and memory usage):
3512
- # dup_table.by_col_or_row['Name']
3513
- #
3514
- # Also note that changes to the duplicate table will not affect the original.
3515
- #
3516
- def by_col_or_row: () -> untyped
3517
-
3518
- # <!--
3519
- # rdoc-file=lib/csv/table.rb
3520
- # - table.by_col_or_row! -> self
3521
- # -->
3522
- # Sets the mode for `self` to mixed mode (see [Mixed
3523
- # Mode](#class-CSV::Table-label-Mixed+Mode)); returns `self`:
3524
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3525
- # table = CSV.parse(source, headers: true).by_col!
3526
- # table.mode # => :col
3527
- # table1 = table.by_col_or_row!
3528
- # table.mode # => :col_or_row
3529
- # table1.equal?(table) # => true # Returned self
3530
- #
3531
- def by_col_or_row!: () -> untyped
3532
-
3533
- # <!--
3534
- # rdoc-file=lib/csv/table.rb
3535
- # - table.by_row -> table_dup
3536
- # -->
3537
- # Returns a duplicate of `self`, in row mode (see [Row
3538
- # Mode](#class-CSV::Table-label-Row+Mode)):
3539
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3540
- # table = CSV.parse(source, headers: true)
3541
- # table.mode # => :col_or_row
3542
- # dup_table = table.by_row
3543
- # dup_table.mode # => :row
3544
- # dup_table.equal?(table) # => false # It's a dup
3545
- #
3546
- # This may be used to chain method calls without changing the mode (but also
3547
- # will affect performance and memory usage):
3548
- # dup_table.by_row[1]
3549
- #
3550
- # Also note that changes to the duplicate table will not affect the original.
3551
- #
3552
- def by_row: () -> untyped
3553
-
3554
- # <!--
3555
- # rdoc-file=lib/csv/table.rb
3556
- # - table.by_row! -> self
3557
- # -->
3558
- # Sets the mode for `self` to row mode (see [Row
3559
- # Mode](#class-CSV::Table-label-Row+Mode)); returns `self`:
3560
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3561
- # table = CSV.parse(source, headers: true)
3562
- # table.mode # => :col_or_row
3563
- # table1 = table.by_row!
3564
- # table.mode # => :row
3565
- # table1.equal?(table) # => true # Returned self
3566
- #
3567
- def by_row!: () -> untyped
3568
-
3569
- # <!--
3570
- # rdoc-file=lib/csv/table.rb
3571
- # - table.delete(*indexes) -> deleted_values
3572
- # - table.delete(*headers) -> deleted_values
3573
- # -->
3574
- # If the access mode is `:row` or `:col_or_row`, and each argument is either an
3575
- # Integer or a Range, returns deleted rows. Otherwise, returns deleted columns
3576
- # data.
3577
- #
3578
- # In either case, the returned values are in the order specified by the
3579
- # arguments. Arguments may be repeated.
3580
- #
3581
- # ---
3582
- #
3583
- # Returns rows as an Array of CSV::Row objects.
3584
- #
3585
- # One index:
3586
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3587
- # table = CSV.parse(source, headers: true)
3588
- # deleted_values = table.delete(0)
3589
- # deleted_values # => [#<CSV::Row "Name":"foo" "Value":"0">]
3590
- #
3591
- # Two indexes:
3592
- # table = CSV.parse(source, headers: true)
3593
- # deleted_values = table.delete(2, 0)
3594
- # deleted_values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
3595
- #
3596
- # ---
3597
- #
3598
- # Returns columns data as column Arrays.
3599
- #
3600
- # One header:
3601
- # table = CSV.parse(source, headers: true)
3602
- # deleted_values = table.delete('Name')
3603
- # deleted_values # => ["foo", "bar", "baz"]
3604
- #
3605
- # Two headers:
3606
- # table = CSV.parse(source, headers: true)
3607
- # deleted_values = table.delete('Value', 'Name')
3608
- # deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]]
3609
- #
3610
- def delete: (*untyped indexes_or_headers) -> untyped
3611
-
3612
- # <!--
3613
- # rdoc-file=lib/csv/table.rb
3614
- # - table.delete_if {|row_or_column| ... } -> self
3615
- # -->
3616
- # Removes rows or columns for which the block returns a truthy value; returns
3617
- # `self`.
3618
- #
3619
- # Removes rows when the access mode is `:row` or `:col_or_row`; calls the block
3620
- # with each CSV::Row object:
3621
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3622
- # table = CSV.parse(source, headers: true)
3623
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3624
- # table.size # => 3
3625
- # table.delete_if {|row| row['Name'].start_with?('b') }
3626
- # table.size # => 1
3627
- #
3628
- # Removes columns when the access mode is `:col`; calls the block with each
3629
- # column as a 2-element array containing the header and an Array of column
3630
- # fields:
3631
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3632
- # table = CSV.parse(source, headers: true)
3633
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3634
- # table.headers.size # => 2
3635
- # table.delete_if {|column_data| column_data[1].include?('2') }
3636
- # table.headers.size # => 1
3637
- #
3638
- # Returns a new Enumerator if no block is given:
3639
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3640
- # table = CSV.parse(source, headers: true)
3641
- # table.delete_if # => #<Enumerator: #<CSV::Table mode:col_or_row row_count:4>:delete_if>
3642
- #
3643
- def delete_if: () { (*untyped) -> untyped } -> untyped
3644
-
3645
- # <!--
3646
- # rdoc-file=lib/csv/table.rb
3647
- # - dig(index_or_header, *index_or_headers)
3648
- # -->
3649
- # Extracts the nested value specified by the sequence of `index` or `header`
3650
- # objects by calling dig at each step, returning nil if any intermediate step is
3651
- # nil.
3652
- #
3653
- def dig: (untyped index_or_header, *untyped index_or_headers) -> untyped
3654
-
3655
- # <!--
3656
- # rdoc-file=lib/csv/table.rb
3657
- # - table.each {|row_or_column| ... ) -> self
3658
- # -->
3659
- # Calls the block with each row or column; returns `self`.
3660
- #
3661
- # When the access mode is `:row` or `:col_or_row`, calls the block with each
3662
- # CSV::Row object:
3663
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3664
- # table = CSV.parse(source, headers: true)
3665
- # table.by_row! # => #<CSV::Table mode:row row_count:4>
3666
- # table.each {|row| p row }
3667
- #
3668
- # Output:
3669
- # #<CSV::Row "Name":"foo" "Value":"0">
3670
- # #<CSV::Row "Name":"bar" "Value":"1">
3671
- # #<CSV::Row "Name":"baz" "Value":"2">
3672
- #
3673
- # When the access mode is `:col`, calls the block with each column as a
3674
- # 2-element array containing the header and an Array of column fields:
3675
- # table.by_col! # => #<CSV::Table mode:col row_count:4>
3676
- # table.each {|column_data| p column_data }
3677
- #
3678
- # Output:
3679
- # ["Name", ["foo", "bar", "baz"]]
3680
- # ["Value", ["0", "1", "2"]]
3681
- #
3682
- # Returns a new Enumerator if no block is given:
3683
- # table.each # => #<Enumerator: #<CSV::Table mode:col row_count:4>:each>
3684
- #
3685
- def each: () -> Enumerator[Elem, self]
3686
- | () { (Elem) -> void } -> self
3687
- | () { (*untyped) -> void } -> self
3688
-
3689
- def empty?: (*untyped args) { (*untyped) -> untyped } -> untyped
3690
-
3691
- # <!--
3692
- # rdoc-file=lib/csv/table.rb
3693
- # - table.headers -> array_of_headers
3694
- # -->
3695
- # Returns a new Array containing the String headers for the table.
3696
- #
3697
- # If the table is not empty, returns the headers from the first row:
3698
- # rows = [
3699
- # CSV::Row.new(['Foo', 'Bar'], []),
3700
- # CSV::Row.new(['FOO', 'BAR'], []),
3701
- # CSV::Row.new(['foo', 'bar'], []),
3702
- # ]
3703
- # table = CSV::Table.new(rows)
3704
- # table.headers # => ["Foo", "Bar"]
3705
- # table.delete(0)
3706
- # table.headers # => ["FOO", "BAR"]
3707
- # table.delete(0)
3708
- # table.headers # => ["foo", "bar"]
3709
- #
3710
- # If the table is empty, returns a copy of the headers in the table itself:
3711
- # table.delete(0)
3712
- # table.headers # => ["Foo", "Bar"]
3713
- #
3714
- def headers: () -> untyped
3715
-
3716
- # <!--
3717
- # rdoc-file=lib/csv/table.rb
3718
- # - table.inspect => string
3719
- # -->
3720
- # Returns a `US-ASCII`-encoded String showing table:
3721
- # * Class: `CSV::Table`.
3722
- # * Access mode: `:row`, `:col`, or `:col_or_row`.
3723
- # * Size: Row count, including the header row.
3724
- #
3725
- # Example:
3726
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3727
- # table = CSV.parse(source, headers: true)
3728
- # table.inspect # => "#<CSV::Table mode:col_or_row row_count:4>\nName,Value\nfoo,0\nbar,1\nbaz,2\n"
3729
- #
3730
- def inspect: () -> String
3731
-
3732
- def length: (*untyped args) { (*untyped) -> untyped } -> untyped
3733
-
3734
- # <!-- rdoc-file=lib/csv/table.rb -->
3735
- # The current access mode for indexing and iteration.
3736
- #
3737
- def mode: () -> untyped
3738
-
3739
- # <!--
3740
- # rdoc-file=lib/csv/table.rb
3741
- # - table.push(*rows_or_arrays) -> self
3742
- # -->
3743
- # A shortcut for appending multiple rows. Equivalent to:
3744
- # rows.each {|row| self << row }
3745
- #
3746
- # Each argument may be either a CSV::Row object or an Array:
3747
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3748
- # table = CSV.parse(source, headers: true)
3749
- # rows = [
3750
- # CSV::Row.new(table.headers, ['bat', 3]),
3751
- # ['bam', 4]
3752
- # ]
3753
- # table.push(*rows)
3754
- # table[3..4] # => [#<CSV::Row "Name":"bat" "Value":3>, #<CSV::Row "Name":"bam" "Value":4>]
3755
- #
3756
- def push: (*untyped rows) -> untyped
3757
-
3758
- def size: (*untyped args) { (*untyped) -> untyped } -> untyped
3759
-
3760
- # <!--
3761
- # rdoc-file=lib/csv/table.rb
3762
- # - table.to_a -> array_of_arrays
3763
- # -->
3764
- # Returns the table as an Array of Arrays; the headers are in the first row:
3765
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3766
- # table = CSV.parse(source, headers: true)
3767
- # table.to_a # => [["Name", "Value"], ["foo", "0"], ["bar", "1"], ["baz", "2"]]
3768
- #
3769
- def to_a: () -> untyped
3770
-
3771
- # <!--
3772
- # rdoc-file=lib/csv/table.rb
3773
- # - table.to_csv(**options) -> csv_string
3774
- # -->
3775
- # Returns the table as CSV string. See [Options for
3776
- # Generating](../CSV.html#class-CSV-label-Options+for+Generating).
3777
- #
3778
- # Defaults option `write_headers` to `true`:
3779
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3780
- # table = CSV.parse(source, headers: true)
3781
- # table.to_csv # => "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3782
- #
3783
- # Omits the headers if option `write_headers` is given as `false` (see {Option
3784
- # `write_headers`[}](../CSV.html#class-CSV-label-Option+write_headers)):
3785
- # table.to_csv(write_headers: false) # => "foo,0\nbar,1\nbaz,2\n"
3786
- #
3787
- # Limit rows if option `limit` is given like `2`:
3788
- # table.to_csv(limit: 2) # => "Name,Value\nfoo,0\nbar,1\n"
3789
- #
3790
- def to_csv: (?write_headers: boolish, **untyped) -> untyped
3791
-
3792
- # <!--
3793
- # rdoc-file=lib/csv/table.rb
3794
- # - to_s(write_headers: true, limit: nil, **options)
3795
- # -->
3796
- #
3797
- alias to_s to_csv
3798
-
3799
- # <!--
3800
- # rdoc-file=lib/csv/table.rb
3801
- # - table.values_at(*indexes) -> array_of_rows
3802
- # - table.values_at(*headers) -> array_of_columns_data
3803
- # -->
3804
- # If the access mode is `:row` or `:col_or_row`, and each argument is either an
3805
- # Integer or a Range, returns rows. Otherwise, returns columns data.
3806
- #
3807
- # In either case, the returned values are in the order specified by the
3808
- # arguments. Arguments may be repeated.
3809
- #
3810
- # ---
3811
- #
3812
- # Returns rows as an Array of CSV::Row objects.
3813
- #
3814
- # No argument:
3815
- # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
3816
- # table = CSV.parse(source, headers: true)
3817
- # table.values_at # => []
3818
- #
3819
- # One index:
3820
- # values = table.values_at(0)
3821
- # values # => [#<CSV::Row "Name":"foo" "Value":"0">]
3822
- #
3823
- # Two indexes:
3824
- # values = table.values_at(2, 0)
3825
- # values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
3826
- #
3827
- # One Range:
3828
- # values = table.values_at(1..2)
3829
- # values # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
3830
- #
3831
- # Ranges and indexes:
3832
- # values = table.values_at(0..1, 1..2, 0, 2)
3833
- # pp values
3834
- #
3835
- # Output:
3836
- # [#<CSV::Row "Name":"foo" "Value":"0">,
3837
- # #<CSV::Row "Name":"bar" "Value":"1">,
3838
- # #<CSV::Row "Name":"bar" "Value":"1">,
3839
- # #<CSV::Row "Name":"baz" "Value":"2">,
3840
- # #<CSV::Row "Name":"foo" "Value":"0">,
3841
- # #<CSV::Row "Name":"baz" "Value":"2">]
3842
- #
3843
- # ---
3844
- #
3845
- # Returns columns data as row Arrays, each consisting of the specified columns
3846
- # data for that row:
3847
- # values = table.values_at('Name')
3848
- # values # => [["foo"], ["bar"], ["baz"]]
3849
- # values = table.values_at('Value', 'Name')
3850
- # values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]]
3851
- #
3852
- def values_at: (*untyped indices_or_headers) -> untyped
3853
- end
3854
-
3855
- %a{annotate:rdoc:skip}
3856
- class Array[unchecked out Elem] < Object
3857
- # Equivalent to CSV::generate_line(self, options)
3858
- #
3859
- # ["CSV", "data"].to_csv
3860
- # #=> "CSV,data\n"
3861
- def to_csv: (**untyped options) -> String
3862
- end
3863
-
3864
- %a{annotate:rdoc:skip}
3865
- class String
3866
- # Equivalent to CSV::parse_line(self, options)
3867
- #
3868
- # "CSV,data".parse_csv
3869
- # #=> ["CSV", "data"]
3870
- def parse_csv: (**untyped options) -> ::Array[String?]?
3871
- end