### Define CSV string for examples Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/field_size_limit.rdoc Defines a multi-line string that will be used in subsequent CSV parsing examples. ```ruby str = <<~EOT "a","b" " 2345 ","" EOT ``` -------------------------------- ### Setting up CSV parsing context Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/header_converters.rdoc Initializes the string and base table parsing used in subsequent examples. ```ruby str = <<-EOT Name,Value foo,0 bar,1 baz,2 EOT # With no header converter table = CSV.parse(str, headers: true) table.headers # => ["Name", "Value"] ``` -------------------------------- ### Define CSV input string for examples Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/skip_blanks.rdoc Sets up a multi-line string containing blank lines for testing CSV parsing options. ```ruby str = <<-EOT foo,0 bar,1 baz,2 , EOT ``` -------------------------------- ### Generate CSV Line With Multiple Write Converters Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/write_converters.rdoc Uses an array of converters to process fields sequentially. In this example, fields are first converted to uppercase and then to lowercase, resulting in their original case but demonstrating the order of execution. ```ruby upcase_converter = proc {|field| field.upcase } downcase_converter = proc {|field| field.downcase } write_converters = [upcase_converter, downcase_converter] str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters) str # => "a,b,c\n" ``` -------------------------------- ### Filter String to IO Stream Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/filtering.rdoc Examples for filtering CSV data from a string to an IO stream. ```ruby in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" path = 't.csv' File.open(path, 'w') do |out_io| CSV.filter(in_string, out_io, headers: true) do |row| row['Name'] = row['Name'].upcase row['Value'] *= 4 end end p File.read(path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n" ``` ```ruby in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" path = 't.csv' File.open(path, 'w') do |out_io| CSV.filter(in_string, out_io, headers: true, out_write_headers: true ) do |row| unless row.is_a?(Array) row['Name'] = row['Name'].upcase row['Value'] *= 4 end end end p File.read(path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n" ``` -------------------------------- ### Filter String to String Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/filtering.rdoc Examples for filtering CSV data between two strings. ```ruby in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" out_string = '' CSV.filter(in_string, out_string, headers: true) do |row| row['Name'] = row['Name'].upcase row['Value'] *= 4 end out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n" ``` ```ruby in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" out_string = '' CSV.filter(in_string, out_string, headers: true, out_write_headers: true) do |row| unless row.is_a?(Array) row['Name'] = row['Name'].upcase row['Value'] *= 4 end end out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n" ``` ```ruby in_string = "foo,0\nbar,1\nbaz,2\n" out_string = '' CSV.filter(in_string, out_string) do |row| row[0] = row[0].upcase row[1] *= 4 end out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n" ``` -------------------------------- ### CSV Parsing with skip_lines as String Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/skip_lines.rdoc A String provided to skip_lines is converted to a Regexp. This example skips lines starting with '#'. ```ruby str = <<-EOT # Comment foo,0 bar,1 baz,2 # Another comment EOT ary = CSV.parse(str, skip_lines: '#') ary ``` -------------------------------- ### CSV Parsing with skip_lines as Regexp Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/skip_lines.rdoc Use a Regexp with skip_lines to ignore lines that match the pattern. This example skips lines starting with '#'. ```ruby str = <<-EOT # Comment foo,0 bar,1 baz,2 # Another comment EOT ary = CSV.parse(str, skip_lines: /^#) ary ``` -------------------------------- ### Parse CSV line without converters (float example) Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/converters.rdoc Demonstrates parsing a CSV string containing a float without any converters. ```ruby str = '1,3.14159' # Without converters array = CSV.parse_line(str) array # => ["1", "3.14159"] ``` -------------------------------- ### Convert Assorted Fields to Objects Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Shows how to apply multiple built-in converters to different fields in a CSV. Ensure 'csv' is required. ```ruby require 'csv' data = "name,age,score\nAlice,30,95.5\nBob,25,88.0" CSV.parse(data, headers: true, converters: [:integer, :float]) do |row| puts "Name: #{row['name']}, Age: #{row['age'].class}, Score: #{row['score'].class}" end ``` -------------------------------- ### Using a list of header converters Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/header_converters.rdoc Applies multiple converters sequentially to the header row. ```ruby header_converters = [:downcase, :symbol] table = CSV.parse(str, headers: true, header_converters: header_converters) table.headers # => [:name, :value] ``` -------------------------------- ### Write CSV with headers Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/write_headers.rdoc Demonstrates writing to a CSV file with the `write_headers` option set to true. This ensures the header row is included in the output. ```ruby CSV.open(file_path,'w', :write_headers => true, :headers => ['Name','Value'] ) do |csv| csv << ['foo', '0'] end CSV.open(file_path) do |csv| csv.shift end # => ["Name", "Value"] ``` -------------------------------- ### Parse CSV from File with Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use CSV.read for full file ingestion or CSV.foreach for memory-efficient row-by-row iteration with headers. ```ruby string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" path = 't.csv' File.write(path, string) CSV.read(path, headers: true) # => # ``` ```ruby CSV.foreach(path, headers: true) do |row| p row end ``` -------------------------------- ### Convert Fields to DateTimes Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to DateTime objects using a built-in converter. Ensure 'csv' is required. ```ruby require 'csv' data = "timestamp,value\n2023-10-26T10:00:00Z,100\n2023-10-26T12:30:00Z,200" CSV.parse(data, headers: true, converters: :datetime) do |row| puts "Timestamp: #{row['timestamp'].class}, Value: #{row['value']}" end ``` -------------------------------- ### Generate CSV to IO Stream Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/generating.rdoc Use CSV.new to wrap an existing IO stream for CSV generation. ```ruby path = 't.csv' File.open(path, 'w') do |file| csv = CSV.new(file, headers: ['Name', 'Value'], write_headers: true) csv << ['Foo', 0] csv << ['Bar', 1] csv << ['Baz', 2] end p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n" ``` ```ruby path = 't.csv' File.open(path, 'w') do |file| csv = CSV.new(file) csv << ['Foo', 0] csv << ['Bar', 1] csv << ['Baz', 2] end ``` -------------------------------- ### Apply Multiple Header Converters Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use multiple converters by passing an array to the :header_converters option or registering a custom list. ```ruby source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n" parsed = CSV.parse(source, headers: true, header_converters: [:downcase, :symbol]) parsed.headers # => [:name, :value] ``` ```ruby CSV::HeaderConverters[:my_header_converters] = [:symbol, :downcase] source = "NAME,VALUE\nfoo,0\nbar,1.0\nbaz,2.0\n" parsed = CSV.parse(source, headers: true, header_converters: :my_header_converters) parsed.headers # => [:name, :value] ``` -------------------------------- ### Convert Fields to Floats Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to floating-point numbers using a built-in converter. Ensure 'csv' is required. ```ruby require 'csv' data = "item,price\nApple,0.5\nBanana,0.25" CSV.parse(data, headers: true, converters: :float) do |row| puts "Item: #{row['item']}, Price: #{row['price'].class}" end ``` -------------------------------- ### Configuring return_headers in CSV Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/return_headers.rdoc Demonstrates how return_headers affects the output of the shift method when parsing CSV data. ```ruby str = <<-EOT Name,Count foo,0 bar,1 bax,2 EOT # Without return_headers first row is str. csv = CSV.new(str, headers: true) csv.shift # => # # With return_headers first row is headers. csv = CSV.new(str, headers: true, return_headers: true) csv.shift # => # ``` -------------------------------- ### Using a custom Proc header converter Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/header_converters.rdoc Applies a custom Proc to transform header fields. ```ruby upcase_converter = proc {|field| field.upcase } table = CSV.parse(str, headers: true, header_converters: upcase_converter) table.headers # => ["NAME", "VALUE"] ``` -------------------------------- ### Convert Fields to Integers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to integers using a built-in converter. Ensure 'csv' is required. ```ruby require 'csv' data = "name,age\nAlice,30\nBob,25" CSV.parse(data, headers: true, converters: :integer) do |row| puts "Name: #{row['name']}, Age: #{row['age'].class}" end ``` -------------------------------- ### Convert Fields to Dates Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to Date objects using a built-in converter. Ensure 'csv' is required. ```ruby require 'csv' data = "event,date\nMeeting,2023-10-26\nParty,2023-11-15" CSV.parse(data, headers: true, converters: :date) do |row| puts "Event: #{row['event']}, Date: #{row['date'].class}" end ``` -------------------------------- ### Generate CSV to File Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/generating.rdoc Use CSV.open to write CSV data directly to a file path. ```ruby path = 't.csv' CSV.open(path, 'w', headers: ['Name', 'Value'], write_headers: true) do |csv| csv << ['Foo', 0] csv << ['Bar', 1] csv << ['Baz', 2] end p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n" ``` ```ruby path = 't.csv' CSV.open(path, 'w') do |csv| csv << ['Foo', 0] csv << ['Bar', 1] csv << ['Baz', 2] end p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n" ``` -------------------------------- ### Parsing CSV with strip option Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/strip.rdoc Demonstrates the difference in output when parsing a CSV string with and without the strip option enabled. ```ruby ary = CSV.parse_line(' a , b ') ary # => [" a ", " b "] ``` ```ruby ary = CSV.parse_line(' a , b ', strip: true) ary # => ["a", "b"] ``` -------------------------------- ### Convert Fields to Other Objects Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to custom object types using a block as a converter. Ensure 'csv' is required. ```ruby require 'csv' class MyObject attr_reader :value def initialize(value) @value = value.to_i * 2 end end data = "id,factor\n1,10\n2,20" CSV.parse(data, headers: true, converters: lambda { |field| MyObject.new(field) }) do |row| puts "ID: #{row['id'].value}, Factor: #{row['factor'].value}" end ``` -------------------------------- ### CSV Initialization with Non-String Quote Character Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/quote_char.rdoc Demonstrates that initializing CSV with a quote_char that is not a string (e.g., a symbol) raises an ArgumentError. ```ruby # Raises ArgumentError (:quote_char has to be nil or a single character String) CSV.new('', quote_char: :foo) ``` -------------------------------- ### Convert Fields to Times Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to Time objects using a built-in converter. Ensure 'csv' is required. ```ruby require 'csv' data = "log_time,message\n10:30:00,System start\n11:00:00,User logged in" CSV.parse(data, headers: true, converters: :time) do |row| puts "Log Time: #{row['log_time'].class}, Message: #{row['message']}" end ``` -------------------------------- ### Specify Multiple Header Converters in a Custom Header Converter List Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Applies multiple header converters using a custom list of converter procs or symbols. Ensure 'csv' is required. ```ruby require 'csv' def custom_header_downcase(header) header.downcase end def custom_header_symbol(header) header.to_sym end data = "First Name,Last Name\nAlice,Smith" CSV.parse(data, headers: true, header_converters: [method(:custom_header_downcase), method(:custom_header_symbol)]) do |row| puts row[:'first_name'] end ``` -------------------------------- ### Using built-in header converters Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/header_converters.rdoc Applies a single built-in converter to the header row. ```ruby table = CSV.parse(str, headers: true, header_converters: :downcase) table.headers # => ["name", "value"] ``` -------------------------------- ### Convert Assorted Fields to Objects Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Uses the built-in :all converter to automatically detect and convert field types. ```ruby source = "Type,Value\nInteger,0\nFloat,1.0\nDateTime,2001-02-04\n" parsed = CSV.parse(source, headers: true, converters: :all) parsed.map {|row| row['Value'].class} # => [Integer, Float, DateTime] ``` -------------------------------- ### Generate Compliant Column Separator Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/generating.rdoc Demonstrates default comma-separated generation which is compliant with RFC 4180. ```ruby output_string = CSV.generate('') do |csv| csv << ['Foo', 0] csv << ['Bar', 1] csv << ['Baz', 2] end output_string # => "Foo,0\nBar,1\nBaz,2\n" ``` -------------------------------- ### CSV Generation with Default Separator (Comma) Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/col_sep.rdoc Demonstrates generating CSV data using the default comma column separator. This is the standard behavior when no `col_sep` is specified. ```ruby str = CSV.generate do |csv| csv << [:foo, 0] csv << [:bar, 1] csv << [:baz, 2] end str # => "foo,0\nbar,1\nbaz,2\n" ary = CSV.parse(str) ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ``` -------------------------------- ### Specify Multiple Header Converters in Option :header_converters Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Applies multiple header converters simultaneously using the :header_converters option. Ensure 'csv' is required. ```ruby require 'csv' data = "First Name,Last Name\nAlice,Smith" CSV.parse(data, headers: true, header_converters: [:downcase, :symbol]) do |row| puts row[:'first_name'] end ``` -------------------------------- ### Custom nil_value Option Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/nil_value.rdoc Shows how to use the nil_value option to replace empty fields with a custom object, such as 0. ```ruby CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"] ``` -------------------------------- ### CSV Parsing with nil_value Option Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/nil_value.rdoc Demonstrates how to use the `nil_value` option to specify a replacement for empty fields during CSV parsing. ```APIDOC ## CSV Parsing with nil_value ### Description Specifies the object that is to be substituted for each null (no-text) field during CSV parsing. ### Method `CSV.parse_line` (or similar CSV parsing methods) ### Parameters #### Query Parameters - **nil_value** (Object) - Optional - The object to substitute for empty fields. Defaults to `nil`. ### Request Example ```ruby # Using the default nil_value (nil) CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"] # Using a custom nil_value (0) CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"] ``` ### Response #### Success Response (Array of Strings/Objects) - The parsed CSV line as an array, with empty fields replaced by the specified `nil_value`. #### Response Example ```ruby # For the default nil_value example: ["a", nil, "b", nil, "c"] # For the custom nil_value example: ["a", 0, "b", 0, "c"] ``` ``` -------------------------------- ### Read CSV File Row by Row Source: https://github.com/ruby/csv/blob/main/README.md Use the `CSV.foreach` method to iterate over each row in a CSV file. Ensure the 'csv' library is required before use. ```ruby require "csv" CSV.foreach("path/to/file.csv") do |row| # use row here... end ``` -------------------------------- ### CSV.generate_line with write_converters Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/write_converters.rdoc Demonstrates how to use the `write_converters` option with `CSV.generate_line` to modify fields before they are written to the CSV string. Converters are applied in the order they are provided. ```APIDOC ## CSV.generate_line with write_converters ### Description Specifies converters to be used in generating fields. These converters are applied in the order they are provided. ### Method `CSV.generate_line(fields, **options)` ### Endpoint N/A (This is a library function, not a web endpoint) ### Parameters #### Keyword Arguments - **write_converters** (Proc or Array of Procs) - Optional - A single converter or an array of converters to apply to each field before writing. ### Request Example ```ruby # Example 1: No write converter str = CSV.generate_line(["\na\n", "\tb\t", " c "]) # str => "\"a\n\",\tb\t, c \n" # Example 2: Single write converter (strip) strip_converter = proc { |field| field.strip } str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter) # str => "a,b,c\n" # Example 3: Multiple write converters (upcase then downcase) upcase_converter = proc { |field| field.upcase } downcase_converter = proc { |field| field.downcase } write_converters = [upcase_converter, downcase_converter] str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters) # str => "a,b,c\n" ``` ### Response #### Success Response (String) Returns a string representing the generated CSV line. #### Response Example (See Request Example for output strings) ### See Also - {Write Converters}[#class-CSV-label-Write+Converters] ``` -------------------------------- ### Parse CSV from a File with Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Parses CSV data from a file, using the first row as headers. Ensure 'csv' is required. ```ruby require 'csv' CSV.foreach('data.csv', headers: true) do |row| puts "Name: #{row['name']}, Age: #{row['age']}" end ``` -------------------------------- ### Check default skip_blanks value Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/skip_blanks.rdoc Retrieves the default configuration value for the skip_blanks option. ```ruby CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false ``` -------------------------------- ### Specify Multiple Field Converters in a Custom Converter List Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Applies multiple field converters using a custom list of converter procs or symbols. Ensure 'csv' is required. ```ruby require 'csv' def to_custom_int(field) field.to_i + 1 end def to_custom_string(field) field.upcase end data = "val1,val2\n1,abc\n2,def" CSV.parse(data, headers: true, converters: [method(:to_custom_int), method(:to_custom_string)]) do |row| puts "Val1: #{row['val1']}, Val2: #{row['val2']}" end ``` -------------------------------- ### Quote All Fields Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/generating.rdoc Forces all fields to be quoted using the force_quotes option. ```ruby output_string = CSV.generate('', force_quotes: true) do |csv| csv << ['Foo', 0] csv << ['Bar', 1] csv << ['Baz', 2] end output_string # => "\"Foo\",\"0\"\n\"Bar\",\"1\"\n\"Baz\",\"2\"\n" ``` -------------------------------- ### Parse CSV from IO Stream with Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use CSV.parse or CSV.foreach on an open IO stream to handle CSV data with headers. ```ruby string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" path = 't.csv' File.write(path, string) File.open(path) do |file| CSV.parse(file, headers: true) end # => # ``` ```ruby File.open(path) do |file| CSV.foreach(file, headers: true) do |row| p row end end ``` -------------------------------- ### CSV.parse_line Configuration Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/empty_value.rdoc Documentation for the empty_value option used in CSV parsing methods. ```APIDOC ## CSV.parse_line ### Description Parses a single line of CSV data. The `empty_value` option specifies the object that is to be substituted for each field that has an empty string. ### Parameters #### Options - **empty_value** (Object) - Optional - The value to substitute for empty fields. Defaults to an empty string (""). ### Request Example ```ruby # Using default empty_value CSV.parse_line('a,"",b,"",c') # Using custom empty_value CSV.parse_line('a,"",b,"",c', empty_value: 'x') ``` ### Response #### Success Response (200) - **Result** (Array) - An array of strings representing the parsed fields, with empty fields replaced by the `empty_value`. ``` -------------------------------- ### Convert Fields to Numerics Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Demonstrates converting CSV fields to numeric types (Integer or Float) using a built-in converter. Ensure 'csv' is required. ```ruby require 'csv' data = "value1,value2\n10,3.14\n20,2.71" CSV.parse(data, headers: true, converters: :numeric) do |row| puts "Value1: #{row['value1'].class}, Value2: #{row['value2'].class}" end ``` -------------------------------- ### Parse CSV with skip_blanks options Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/skip_blanks.rdoc Demonstrates how different values for skip_blanks affect the parsing of blank lines. ```ruby ary = CSV.parse(str) ary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]] ``` ```ruby ary = CSV.parse(str, skip_blanks: true) ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] ``` ```ruby ary = CSV.parse(str, skip_blanks: :foo) ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] ``` -------------------------------- ### CSV Generation and Parsing with Colon Separator Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/col_sep.rdoc Shows how to use a colon (`:`) as the column separator for both generating and parsing CSV data. The `col_sep` option must be provided to both `CSV.generate` and `CSV.parse`. ```ruby col_sep = ':' str = CSV.generate(col_sep: col_sep) do |csv| csv << [:foo, 0] csv << [:bar, 1] csv << [:baz, 2] end str # => "foo:0\nbar:1\nbaz:2\n" ary = CSV.parse(str, col_sep: col_sep) ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ``` -------------------------------- ### Capture Field Info Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Captures detailed information about each field during parsing, including its original value and converted value. Ensure 'csv' is required. ```ruby require 'csv' data = "name,age\nAlice,30" CSV.parse(data, headers: true, header_converters: :symbol, field_info: true) do |row| row.each do |field_info| puts "Field: #{field_info.header}, Original: #{field_info.original_value}, Converted: #{field_info.value}" end end ``` -------------------------------- ### CSV Parsing with return_headers Option Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/return_headers.rdoc This snippet demonstrates how the `return_headers` option affects the behavior of the `shift` method when parsing CSV data. ```APIDOC ## CSV Parsing with return_headers Option ### Description This section details the `return_headers` option for the Ruby CSV parser. When set to `true`, the `shift` method will return the header row. When `false` (the default), the header row is ignored. ### Method N/A (This describes an option, not a specific HTTP method) ### Endpoint N/A (This describes an option, not a specific API endpoint) ### Parameters #### Option: `return_headers` - **return_headers** (boolean) - Optional - Specifies whether the `shift` method should return the header row. Defaults to `false`. ### Request Example ```ruby require 'csv' str = <<-EOT Name,Count foo,0 bar,1 bax,2 EOT # Without return_headers (default behavior) csv_no_headers = CSV.new(str, headers: true) puts csv_no_headers.shift # Output: # # With return_headers enabled csv_with_headers = CSV.new(str, headers: true, return_headers: true) puts csv_with_headers.shift # Output: # ``` ### Response #### Behavior Description - **Default Behavior**: When `return_headers` is `false`, `csv.shift` returns the first data row after the header. - **Enabled Behavior**: When `return_headers` is `true`, `csv.shift` returns the header row itself as a `CSV::Row` object. #### Response Example *Example Output for `csv.shift` when `return_headers: true`* ``` # ``` *Example Output for `csv.shift` when `return_headers: false`* ``` # ``` ``` -------------------------------- ### Filter Header Strings Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Defines a custom header converter to capitalize header strings. ```ruby capitalize_converter = proc {|header| header.capitalize } source = "NAME,VALUE\nfoo,0\nbar,1\nbaz,2\n" parsed = CSV.parse(source, headers: true, header_converters: capitalize_converter) parsed.headers # => ["Name", "Value"] ``` -------------------------------- ### Generate CSV Line with force_quotes Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/force_quotes.rdoc Demonstrates the difference in output when force_quotes is set to false versus true. ```ruby ary = ['foo', 0, nil] ``` ```ruby str = CSV.generate_line(ary) str # => "foo,0,\n" ``` ```ruby str = CSV.generate_line(ary, force_quotes: true) str # => "\"foo\",\"0\",\"\"\n" ``` -------------------------------- ### Ignore Blank Lines in CSV Parsing Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Configures CSV parsing to skip empty lines in the input. Ensure 'csv' is required. ```ruby require 'csv' data = "a,b\n\n c,d" CSV.parse(data, skip_blanks: true) do |row| p row end ``` -------------------------------- ### Convert Fields to Other Objects Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Defines a custom proc to convert specific column values into Rational objects. ```ruby rational_converter = proc do |field, field_context| field_context.index == 1 ? field.to_r : field end source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" parsed = CSV.parse(source, headers: true, converters: rational_converter) parsed.map {|row| row['Value'].class} # => [Rational, Rational, Rational] ``` -------------------------------- ### Default nil_value Behavior Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/nil_value.rdoc Demonstrates the default behavior of CSV parsing where empty fields are represented as nil. ```ruby CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"] ``` -------------------------------- ### Generating CSV Lines with write_empty_value Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/write_empty_value.rdoc Demonstrates the effect of the write_empty_value option on CSV output compared to default behavior. ```ruby str = CSV.generate_line(['a', '', 'c', '']) str # => "a,\"\",c,\"\"\n" ``` ```ruby str = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x") str # => "a,x,c,x\n" ``` -------------------------------- ### Write CSV without headers Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/write_headers.rdoc Demonstrates writing to a CSV file without explicitly enabling the `write_headers` option. The header row is not automatically included. ```ruby file_path = 't.csv' CSV.open(file_path,'w', :headers => ['Name','Value'] ) do |csv| csv << ['foo', '0'] end CSV.open(file_path) do |csv| csv.shift end # => ["foo", "0"] ``` -------------------------------- ### CSV Parsing Without Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/headers.rdoc Demonstrates parsing CSV data without specifying headers. The first row is treated as data, and 'csv.headers' returns nil. ```ruby str = <<-EOT Name,Count foo,0 bar,1 bax,2 EOT csv = CSV.new(str) csv # => # csv.headers # => nil csv.shift # => ["Name", "Count"] ``` -------------------------------- ### Default empty_value behavior Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/empty_value.rdoc Demonstrates the default behavior of CSV.parse_line where empty fields are represented by empty strings. ```ruby CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"] ``` -------------------------------- ### Handle Empty Fields in CSV Parsing Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Configures CSV parsing to treat empty fields as empty strings. This is the default behavior. Ensure 'csv' is required. ```ruby require 'csv' data = "a,,c\n1,2,3" CSV.parse(data, empty_fields: true) do |row| p row end ``` -------------------------------- ### CSV.parse_line Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/strip.rdoc Documentation for the CSV.parse_line method and the strip option. ```APIDOC ## CSV.parse_line ### Description Parses a single line of CSV data into an array. The method supports a strip option to control whitespace handling. ### Parameters #### Options - **strip** (boolean) - Optional - Specifies whether whitespace is stripped from each input field. Defaults to false. ``` -------------------------------- ### Specify Multiple Field Converters in a Custom Converter List Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Registers a list of multiple converters under a single name. ```ruby strip_converter = proc {|field| field.strip } CSV::Converters[:strip] = strip_converter CSV::Converters[:my_converters] = [:integer, :float, :strip] source = "Name,Value\n foo , 0 \n bar , 1.0 \n baz , 2.0 \n" parsed = CSV.parse(source, headers: true, converters: :my_converters) parsed['Name'] # => ["foo", "bar", "baz"] parsed['Value'] # => [0, 1.0, 2.0] ``` -------------------------------- ### Capture Field Metadata Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use a custom converter block accepting a CSV::FieldInfo object to access index, line, and header information. ```ruby strip_converter = proc {|field, field_info| p field_info; field.strip } source = " foo , 0 \n bar , 1 \n baz , 2 \n" parsed = CSV.parse(source, converters: strip_converter) parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ``` -------------------------------- ### Specify Multiple Field Converters in Option :converters Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Applies multiple converters by passing an array to the :converters option. ```ruby source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n" parsed = CSV.parse(source, headers: true, converters: [:integer, :float]) parsed['Value'] # => [0, 1.0, 2.0] ``` -------------------------------- ### Parse CSV from String with Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use CSV.parse for all-at-once parsing or CSV.new with each for row-by-row processing when headers are present. ```ruby string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" CSV.parse(string, headers: true) # => # ``` ```ruby CSV.new(string, headers: true).each do |row| p row end ``` -------------------------------- ### Generate CSV Line With a Single Write Converter Source: https://github.com/ruby/csv/blob/main/doc/csv/options/generating/write_converters.rdoc Applies a strip converter to remove leading and trailing whitespace from each field before generating the CSV line. This simplifies the output by removing unnecessary characters. ```ruby strip_converter = proc {|field| field.strip } str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter) str # => "a,b,c\n" ``` -------------------------------- ### Custom empty_value with CSV.parse_line Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/empty_value.rdoc Shows how to use the empty_value option to substitute a different object for empty fields during CSV line parsing. ```ruby CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"] ``` -------------------------------- ### Convert Headers to Symbols Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Converts all header names to symbols during CSV parsing. Ensure 'csv' is required. ```ruby require 'csv' data = "Name,Age\nAlice,30\nBob,25" CSV.parse(data, headers: true, header_converters: :symbol) do |row| puts row[:name] end ``` -------------------------------- ### Convert Fields to DateTimes Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Uses the built-in :date_time converter to parse date-time strings into DateTime objects. ```ruby source = "Name,DateTime\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2020-05-07T14:59:00-05:00\n" parsed = CSV.parse(source, headers: true, converters: :date_time) parsed.map {|row| row['DateTime'].class} # => [DateTime, DateTime, DateTime] ``` -------------------------------- ### Raise exception with invalid converter name Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/converters.rdoc Demonstrates that providing an invalid converter name to CSV.parse will raise an exception. ```ruby str = 'foo,0' # Raises NoMethodError (undefined method `arity' for nil:NilClass) CSV.parse(str, converters: :foo) ``` -------------------------------- ### Parse CSV from IO Stream without Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use CSV.parse or CSV.foreach on an open IO stream to handle CSV data without headers. ```ruby string = "foo,0\nbar,1\nbaz,2\n" path = 't.csv' File.write(path, string) File.open(path) do |file| CSV.parse(file) end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ``` ```ruby File.open(path) do |file| CSV.foreach(file) do |row| p row end end ``` -------------------------------- ### Parse CSV from File without Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use CSV.read or CSV.foreach to process file-based CSV data without headers. ```ruby string = "foo,0\nbar,1\nbaz,2\n" path = 't.csv' File.write(path, string) CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ``` ```ruby CSV.foreach(path) do |row| p row end ``` -------------------------------- ### CSV Initialization with Invalid Quote Character Length Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/quote_char.rdoc Illustrates that initializing CSV with a quote_char string longer than one character raises an ArgumentError. ```ruby # Raises ArgumentError (:quote_char has to be nil or a single character String) CSV.new('', quote_char: 'xx') ``` -------------------------------- ### CSV Generation and Parsing with Double Colon Separator Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/col_sep.rdoc Illustrates using a double colon (`::`) as the column separator. Similar to the single colon, the `col_sep` option needs to be specified for both generation and parsing. ```ruby col_sep = '::' str = CSV.generate(col_sep: col_sep) do |csv| csv << [:foo, 0] csv << [:bar, 1] csv << [:baz, 2] end str # => "foo::0\nbar::1\nbaz::2\n" ary = CSV.parse(str, col_sep: col_sep) ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ``` -------------------------------- ### Register Header Converters Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Registers custom header converters for reuse. Ensure 'csv' is required. ```ruby require 'csv' CSV::Header.module_eval do def to_custom_header "HEADER_#{self.upcase}" end end data = "name,age\nAlice,30" CSV.parse(data, headers: true, header_converters: :custom_header) do |row| p row.headers end ``` -------------------------------- ### Convert Fields to Dates Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use the :date converter to automatically convert fields representing dates into Ruby Date objects. Ensure dates are in a format Ruby can parse. ```ruby source = "Name,Date\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2001-02-03\n" parsed = CSV.parse(source, headers: true, converters: :date) parsed.map {|row| row['Date'].class} # => [Date, Date, Date] ``` -------------------------------- ### Convert Headers to Lowercase Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Uses the built-in :downcase header converter. ```ruby source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" parsed = CSV.parse(source, headers: true, header_converters: :downcase) parsed.headers # => ["name", "value"] ``` -------------------------------- ### Specify Multiple Write Converters Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/generating.rdoc Applies multiple custom converters to transform fields, such as stripping and upcasing, during generation. ```ruby strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field } converters = [strip_converter, upcase_converter] output_string = CSV.generate(write_converters: converters) do |csv| csv << [' foo ', 0] csv << [' bar ', 1] csv << [' baz ', 2] end output_string # => "FOO,0\nBAR,1\nBAZ,2\n" ``` -------------------------------- ### Handle Non-Compliant Column Separator in CSV Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Allows parsing CSV data with non-standard column separators. Useful for malformed files. Ensure 'csv' is required. ```ruby require 'csv' data = "a|b\nc|d" CSV.parse(data, col_sep: "|") do |row| p row end ``` -------------------------------- ### Parse CSV from an IO Stream with Headers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Parses CSV data from an IO stream, treating the first row as headers. Ensure 'csv' is required. ```ruby require 'csv' require 'stringio' string_io = StringIO.new("name,age\nAlice,30\nBob,25") CSV.parse(string_io, headers: true) do |row| puts "Name: #{row['name']}, Age: #{row['age']}" end ``` -------------------------------- ### Convert Fields to Integers Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use the :integer converter to automatically convert fields that represent integers into Ruby Integer objects. Useful for numerical analysis. ```ruby source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" parsed = CSV.parse(source, headers: true, converters: :integer) parsed.map {|row| row['Value'].class} # => [Integer, Integer, Integer] ``` -------------------------------- ### Register a Custom Header Converter Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Define and register a custom proc to transform CSV headers during parsing. ```ruby capitalize_converter = proc {|header| header.capitalize } CSV::HeaderConverters[:capitalize] = capitalize_converter source = "NAME,VALUE\nfoo,0\nbar,1\nbaz,2\n" parsed = CSV.parse(source, headers: true, header_converters: :capitalize) parsed.headers # => ["Name", "Value"] ``` -------------------------------- ### Filter Header Strings Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Applies string manipulation to header names before they are parsed. Ensure 'csv' is required. ```ruby require 'csv' data = " First Name , Last Name \n Alice , Smith " CSV.parse(data, headers: true, header_converters: lambda { |h| h.strip.downcase.gsub(' ', '_') }) do |row| puts row['first_name'] end ``` -------------------------------- ### CSV Generation with Empty String Separator Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/col_sep.rdoc Demonstrates generating CSV data where the column separator is an empty string. This results in concatenated values within each row. ```ruby col_sep = '' str = CSV.generate(col_sep: col_sep) do |csv| csv << [:foo, 0] csv << [:bar, 1] csv << [:baz, 2] end str # => "foo0\nbar1\nbaz2\n" ``` -------------------------------- ### CSV Parsing with Headers: true Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/headers.rdoc Parses CSV data using the 'headers: true' option. The first row is automatically used as headers, and subsequent rows are parsed as CSV::Row objects. ```ruby str = <<-EOT Name,Count foo,0 bar,1 bax,2 EOT csv = CSV.new(str, headers: true) csv # => # csv.headers # => ["Name", "Count"] csv.shift # => # ``` -------------------------------- ### CSV Parsing with Headers: String Source: https://github.com/ruby/csv/blob/main/doc/csv/options/parsing/headers.rdoc Uses a String for the 'headers' option, which is parsed by 'CSV::parse_line' to define the headers. This is useful for inline header definitions. ```ruby str = <<-EOT foo,0 bar,1 bax,2 EOT csv = CSV.new(str, headers: 'Name,Count') csv csv.headers # => ["Name", "Count"] csv.shift # => # ``` -------------------------------- ### Convert Fields to Floats Source: https://github.com/ruby/csv/blob/main/doc/csv/recipes/parsing.rdoc Use the :float converter to automatically convert fields that represent floating-point numbers into Ruby Float objects. Useful for calculations involving decimals. ```ruby source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" parsed = CSV.parse(source, headers: true, converters: :float) parsed.map {|row| row['Value'].class} # => [Float, Float, Float] ``` -------------------------------- ### CSV Quote Character Configuration Source: https://github.com/ruby/csv/blob/main/doc/csv/options/common/quote_char.rdoc This section details the `quote_char` option for the CSV library, explaining its purpose, default value, and how to use it for custom quoting. ```APIDOC ## CSV Quote Character Option ### Description Specifies the character used to quote fields in both parsing and generating CSV data. This character will be transcoded into the data's encoding before use. ### Default Value The default `quote_char` is `"` (double quote), accessed via `CSV::DEFAULT_OPTIONS.fetch(:quote_char)`. ### Usage Examples **Using the default (double quote):** ```ruby str = CSV.generate do |csv| csv << ['foo', 0] csv << ["'bar'", 1] csv << ['"baz"', 2] end puts str # Output: # foo,0 # 'bar',1 # """baz""",2 ary = CSV.parse(str) puts ary.inspect # Output: # [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] ``` **Using a custom single quote character:** ```ruby quote_char = "'" str = CSV.generate(quote_char: quote_char) do |csv| csv << ['foo', 0] csv << ["'bar'", 1] csv << ['"baz"', 2] end puts str # Output: # foo,0 # '''bar''',1 # "baz",2 ary = CSV.parse(str, quote_char: quote_char) puts ary.inspect # Output: # [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] ``` ### Error Handling **Raises an exception if the `quote_char` string length is greater than 1:** ```ruby # Raises ArgumentError (:quote_char has to be nil or a single character String) CSV.new('', quote_char: 'xx') ``` **Raises an exception if the `quote_char` value is not a String:** ```ruby # Raises ArgumentError (:quote_char has to be nil or a single character String) CSV.new('', quote_char: :foo) ``` ```