ruby-changes:62307
From: Burdette <ko1@a...>
Date: Mon, 20 Jul 2020 03:35:57 +0900 (JST)
Subject: [ruby-changes:62307] d9749b4715 (master): [ruby/csv] RDoc for converters (#157)
https://git.ruby-lang.org/ruby.git/commit/?id=d9749b4715 From d9749b4715168ccce020dd43b4815e365881f73e Mon Sep 17 00:00:00 2001 From: Burdette Lamar <BurdetteLamar@Y...> Date: Wed, 15 Jul 2020 15:37:17 -0500 Subject: [ruby/csv] RDoc for converters (#157) * More on RDoc for converters * More on RDoc for converters * Fix indent Co-authored-by: Sutou Kouhei <kou@c...> https://github.com/ruby/csv/commit/6044976160 diff --git a/doc/csv/options/generating/write_converters.rdoc b/doc/csv/options/generating/write_converters.rdoc index c7367b9..6e5fae5 100644 --- a/doc/csv/options/generating/write_converters.rdoc +++ b/doc/csv/options/generating/write_converters.rdoc @@ -1,7 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/doc/csv/options/generating/write_converters.rdoc#L1 ====== Option +write_converters+ -Specifies the \Proc or \Array of Procs that are to be called -for converting each output field. +Specifies converters to be used in generating fields. +See {Write Converters}[#class-CSV-label-Write+Converters] Default value: CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil @@ -11,21 +11,23 @@ With no write converter: https://github.com/ruby/ruby/blob/trunk/doc/csv/options/generating/write_converters.rdoc#L11 str # => "\"\na\n\",\tb\t, c \n" With a write converter: - strip_converter = lambda {|field| field.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" With two write converters (called in order): - upcase_converter = lambda {|field| field.upcase } - downcase_converter = lambda {|field| field.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" +See also {Write Converters}[#class-CSV-label-Write+Converters] + --- Raises an exception if the converter returns a value that is neither +nil+ nor \String-convertible: - bad_converter = lambda {|field| BasicObject.new } + bad_converter = proc {|field| BasicObject.new } # Raises NoMethodError (undefined method `is_a?' for #<BasicObject:>) CSV.generate_line(['a', 'b', 'c'], write_converters: bad_converter) \ No newline at end of file diff --git a/doc/csv/options/parsing/converters.rdoc b/doc/csv/options/parsing/converters.rdoc index 993803c..211fa48 100644 --- a/doc/csv/options/parsing/converters.rdoc +++ b/doc/csv/options/parsing/converters.rdoc @@ -1,41 +1,42 @@ https://github.com/ruby/ruby/blob/trunk/doc/csv/options/parsing/converters.rdoc#L1 ====== Option +converters+ -Specifies a single field converter name or \Proc, -or an \Array of field converter names and Procs. - +Specifies converters to be used in parsing fields. See {Field Converters}[#class-CSV-label-Field+Converters] Default value: CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil -The value may be a single field converter name: +The value may be a field converter name +(see {Stored Converters}[#class-CSV-label-Stored+Converters]): str = '1,2,3' # Without a converter - ary = CSV.parse_line(str) - ary # => ["1", "2", "3"] + array = CSV.parse_line(str) + array # => ["1", "2", "3"] # With built-in converter :integer - ary = CSV.parse_line(str, converters: :integer) - ary # => [1, 2, 3] + array = CSV.parse_line(str, converters: :integer) + array # => [1, 2, 3] -The value may be an \Array of field converter names: +The value may be a converter list +(see {Converter Lists}[#class-CSV-label-Converter+Lists]): str = '1,3.14159' # Without converters - ary = CSV.parse_line(str) - ary # => ["1", "3.14159"] + array = CSV.parse_line(str) + array # => ["1", "3.14159"] # With built-in converters - ary = CSV.parse_line(str, converters: [:integer, :float]) - ary # => [1, 3.14159] + array = CSV.parse_line(str, converters: [:integer, :float]) + array # => [1, 3.14159] The value may be a \Proc custom converter: +(see {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]): str = ' foo , bar , baz ' # Without a converter - ary = CSV.parse_line(str) - ary # => [" foo ", " bar ", " baz "] + array = CSV.parse_line(str) + array # => [" foo ", " bar ", " baz "] # With a custom converter - ary = CSV.parse_line(str, converters: proc {|field| field.strip }) - ary # => ["foo", "bar", "baz"] + array = CSV.parse_line(str, converters: proc {|field| field.strip }) + array # => ["foo", "bar", "baz"] -See also {Custom Converters}[#class-CSV-label-Custom+Converters] +See also {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters] --- diff --git a/doc/csv/options/parsing/header_converters.rdoc b/doc/csv/options/parsing/header_converters.rdoc index 329d96a..3091808 100644 --- a/doc/csv/options/parsing/header_converters.rdoc +++ b/doc/csv/options/parsing/header_converters.rdoc @@ -1,6 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/doc/csv/options/parsing/header_converters.rdoc#L1 ====== Option +header_converters+ -Specifies a \String converter name or an \Array of converter names. +Specifies converters to be used in parsing headers. +See {Header Converters}[#class-CSV-label-Header+Converters] Default value: CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil @@ -10,22 +11,33 @@ except that: https://github.com/ruby/ruby/blob/trunk/doc/csv/options/parsing/header_converters.rdoc#L11 - The converters apply only to the header row. - The built-in header converters are +:downcase+ and +:symbol+. -Examples: +This section assumes prior execution of: str = <<-EOT + Name,Value foo,0 bar,1 baz,2 EOT - headers = ['Name', 'Value'] # With no header converter - csv = CSV.parse(str, headers: headers) - csv.headers # => ["Name", "Value"] - # With header converter :downcase - csv = CSV.parse(str, headers: headers, header_converters: :downcase) - csv.headers # => ["name", "value"] - # With header converter :symbol - csv = CSV.parse(str, headers: headers, header_converters: :symbol) - csv.headers # => [:name, :value] - # With both - csv = CSV.parse(str, headers: headers, header_converters: [:downcase, :symbol]) - csv.headers # => [:name, :value] + table = CSV.parse(str, headers: true) + table.headers # => ["Name", "Value"] + +The value may be a header converter name +(see {Stored Converters}[#class-CSV-label-Stored+Converters]): + table = CSV.parse(str, headers: true, header_converters: :downcase) + table.headers # => ["name", "value"] + +The value may be a converter list +(see {Converter Lists}[#class-CSV-label-Converter+Lists]): + header_converters = [:downcase, :symbol] + table = CSV.parse(str, headers: true, header_converters: header_converters) + table.headers # => [:name, :value] + +The value may be a \Proc custom converter +(see {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]): + upcase_converter = proc {|field| field.upcase } + table = CSV.parse(str, headers: true, header_converters: upcase_converter) + table.headers # => ["NAME", "VALUE"] + +See also {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters] + diff --git a/lib/csv.rb b/lib/csv.rb index 6efb3ab..8389889 100644 --- a/lib/csv.rb +++ b/lib/csv.rb @@ -34,7 +34,7 @@ https://github.com/ruby/ruby/blob/trunk/lib/csv.rb#L34 # I'm sure I'll miss something, but I'll try to mention most of the major # differences I am aware of, to help others quickly get up to speed: # -# === CSV Parsing +# === \CSV Parsing # # * This parser is m17n aware. See CSV for full details. # * This library has a stricter parser and will throw MalformedCSVErrors on @@ -440,54 +440,188 @@ using CSV::MatchP if CSV.const_defined?(:MatchP) https://github.com/ruby/ruby/blob/trunk/lib/csv.rb#L440 # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary]) # data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000"> # -# === \CSV \Converters +# === \Converters +# +# By default, each value (field or header) parsed by \CSV is formed into a \String. +# You can use a _field_ _converter_ or _header_ _converter_ +# to intercept and modify the parsed values: +# - See {Field Converters}[#class-CSV-label-Field+Converters]. +# - See {Header Converters}[#class-CSV-label-Header+Converters]. +# +# Also by default, each value to be written during generation is written 'as-is'. +# You can use a _write_ _converter_ to modify values before writing. +# - See {Write Converters}[#class-CSV-label-Write+Converters]. +# +# ==== Specifying \Converters +# +# You can specify converters for parsing or generating in the +options+ +# argument to various \CSV methods: +# - Option +converters+ for converting parsed field values. +# - Option +header_converters+ for converting parsed header values. +# - Option +write_converters+ for converting values to be written (generated). +# +# There are three forms for specifying converters: +# - A converter proc: executable code to be used for conversion. +# - A converter name: the name of a stored converter. +# - A converter list: an array of converter procs, converter names, and converter lists. +# +# ===== Converter Procs +# +# This converter proc, +strip_converter+, accepts a value +field+ +# and returns <tt>field.strip</tt>: +# strip_converter = proc {|field| field.strip } +# In this call to <tt>CSV.parse</tt>, +# the keyword argument <tt>converters: string_converter</tt> +# specifies that: +# - \Proc +string_converter+ is to be called for each parsed field. +# - The converter's return value is to replace the +field+ value. +# Example: +# string = " foo , 0 \n bar , 1 \n baz , 2 \n" +# array = CSV.parse(string, converters: strip_converter) +# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] +# +# A converter proc can receive a second argument, +field_info+, +# that contains details about the field. +# This modified (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/