Skip to content

Commit e8954fa

Browse files
BurdetteLamarkou
authored andcommitted
[ruby/csv] Enhanced RDoc for CSV::Row (#171)
ruby/csv@cced8d8de9
1 parent 31ccc23 commit e8954fa

File tree

2 files changed

+119
-31
lines changed

2 files changed

+119
-31
lines changed

lib/csv/.editorconfig

Whitespace-only changes.

lib/csv/row.rb

Lines changed: 119 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -279,17 +279,34 @@ def []=(*args)
279279

280280
#
281281
# :call-seq:
282-
# <<( field )
283-
# <<( header_and_field_array )
284-
# <<( header_and_field_hash )
282+
# row << [header, value] -> self
283+
# row << hash -> self
284+
# row << value -> self
285285
#
286-
# If a two-element Array is provided, it is assumed to be a header and field
287-
# and the pair is appended. A Hash works the same way with the key being
288-
# the header and the value being the field. Anything else is assumed to be
289-
# a lone field which is appended with a +nil+ header.
286+
# Adds a field to +self+; returns +self+:
290287
#
291-
# This method returns the row for chaining.
288+
# If the argument is a 2-element \Array <tt>[header, value]</tt>,
289+
# a field is added with the given +header+ and +value+:
290+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
291+
# table = CSV.parse(source, headers: true)
292+
# row = table[0]
293+
# row << ['NAME', 'Bat']
294+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
295+
#
296+
# If the argument is a \Hash, each <tt>key-value</tt> pair is added
297+
# as a field with header +key+ and value +value+.
298+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
299+
# table = CSV.parse(source, headers: true)
300+
# row = table[0]
301+
# row << {NAME: 'Bat', name: 'Bam'}
302+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
292303
#
304+
# Otherwise, the given +value+ is added as a field with no header.
305+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
306+
# table = CSV.parse(source, headers: true)
307+
# row = table[0]
308+
# row << 'Bag'
309+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
293310
def <<(arg)
294311
if arg.is_a?(Array) and arg.size == 2 # appending a header and name
295312
@row << arg
@@ -302,13 +319,15 @@ def <<(arg)
302319
self # for chaining
303320
end
304321

322+
# :call-seq:
323+
# row.push(*values) ->self
305324
#
306-
# A shortcut for appending multiple fields. Equivalent to:
307-
#
308-
# args.each { |arg| csv_row << arg }
309-
#
310-
# This method returns the row for chaining.
311-
#
325+
# Appends each of the given +values+ to +self+ as a field; returns +self+:
326+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
327+
# table = CSV.parse(source, headers: true)
328+
# row = table[0]
329+
# row.push('Bat', 'Bam')
330+
# row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
312331
def push(*args)
313332
args.each { |arg| self << arg }
314333

@@ -317,14 +336,39 @@ def push(*args)
317336

318337
#
319338
# :call-seq:
320-
# delete( header )
321-
# delete( header, offset )
322-
# delete( index )
339+
# delete(index) -> [header, value] or nil
340+
# delete(header) -> [header, value] or empty_array
341+
# delete(header, offset) -> [header, value] or empty_array
342+
#
343+
# Removes a specified field from +self+; returns the 2-element \Array
344+
# <tt>[header, value]</tt> if the field exists.
323345
#
324-
# Removes a pair from the row by +header+ or +index+. The pair is
325-
# located as described in CSV::Row.field(). The deleted pair is returned,
326-
# or +nil+ if a pair could not be found.
346+
# If an \Integer argument +index+ is given,
347+
# removes and returns the field at offset +index+,
348+
# or returns +nil+ if the field does not exist:
349+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
350+
# table = CSV.parse(source, headers: true)
351+
# row = table[0]
352+
# row.delete(1) # => ["Name", "Bar"]
353+
# row.delete(50) # => nil
327354
#
355+
# Otherwise, if the single argument +header+ is given,
356+
# removes and returns the first-found field with the given header,
357+
# of returns a new empty \Array if the field does not exist:
358+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
359+
# table = CSV.parse(source, headers: true)
360+
# row = table[0]
361+
# row.delete('Name') # => ["Name", "Foo"]
362+
# row.delete('NAME') # => []
363+
#
364+
# If argument +header+ and \Integer argument +offset+ are given,
365+
# removes and returns the first-found field with the given header
366+
# whose +index+ is at least as large as +offset+:
367+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
368+
# table = CSV.parse(source, headers: true)
369+
# row = table[0]
370+
# row.delete('Name', 1) # => ["Name", "Bar"]
371+
# row.delete('NAME', 1) # => []
328372
def delete(header_or_index, minimum_index = 0)
329373
if header_or_index.is_a? Integer # by index
330374
@row.delete_at(header_or_index)
@@ -335,15 +379,21 @@ def delete(header_or_index, minimum_index = 0)
335379
end
336380
end
337381

382+
# :call-seq:
383+
# row.delete_if {|header, value| ... } -> self
338384
#
339-
# The provided +block+ is passed a header and field for each pair in the row
340-
# and expected to return +true+ or +false+, depending on whether the pair
341-
# should be deleted.
342-
#
343-
# This method returns the row for chaining.
385+
# Removes fields from +self+ as selected by the block; returns +self+.
344386
#
345-
# If no block is given, an Enumerator is returned.
387+
# Removes each field for which the block returns a truthy value:
388+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
389+
# table = CSV.parse(source, headers: true)
390+
# row = table[0]
391+
# row.delete_if {|header, value| value.start_with?('B') } # => true
392+
# row # => #<CSV::Row "Name":"Foo">
393+
# row.delete_if {|header, value| header.start_with?('B') } # => false
346394
#
395+
# If no block is given, returns a new Enumerator:
396+
# row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
347397
def delete_if(&block)
348398
return enum_for(__method__) { size } unless block_given?
349399

@@ -352,14 +402,52 @@ def delete_if(&block)
352402
self # for chaining
353403
end
354404

405+
# :call-seq:
406+
# self.fields(*specifiers)
355407
#
356-
# This method accepts any number of arguments which can be headers, indices,
357-
# Ranges of either, or two-element Arrays containing a header and offset.
358-
# Each argument will be replaced with a field lookup as described in
359-
# CSV::Row.field().
408+
# Returns field values per the given +specifiers+, which may be any mixture of:
409+
# - \Integer index.
410+
# - \Range of \Integer indexes.
411+
# - 2-element \Array containing a header and offset.
412+
# - Header.
413+
# - \Range of headers.
360414
#
361-
# If called with no arguments, all fields are returned.
415+
# For +specifier+ in one of the first four cases above,
416+
# returns the result of <tt>self.field(specifier)</tt>; see #field.
417+
#
418+
# Although there may be any number of +specifiers+,
419+
# the examples here will illustrate one at a time.
420+
#
421+
# When the specifier is an \Integer +index+,
422+
# returns <tt>self.field(index)</tt>L
423+
# source = "Name,Name,Name\nFoo,Bar,Baz\n"
424+
# table = CSV.parse(source, headers: true)
425+
# row = table[0]
426+
# row.fields(1) # => ["Bar"]
427+
#
428+
# When the specifier is a \Range of \Integers +range+,
429+
# returns <tt>self.field(range)</tt>:
430+
# row.fields(1..2) # => ["Bar", "Baz"]
431+
#
432+
# When the specifier is a 2-element \Array +array+,
433+
# returns <tt>self.field(array)</tt>L
434+
# row.fields('Name', 1) # => ["Foo", "Bar"]
435+
#
436+
# When the specifier is a header +header+,
437+
# returns <tt>self.field(header)</tt>L
438+
# row.fields('Name') # => ["Foo"]
439+
#
440+
# When the specifier is a \Range of headers +range+,
441+
# forms a new \Range +new_range+ from the indexes of
442+
# <tt>range.start</tt> and <tt>range.end</tt>,
443+
# and returns <tt>self.field(new_range)</tt>:
444+
# source = "Name,NAME,name\nFoo,Bar,Baz\n"
445+
# table = CSV.parse(source, headers: true)
446+
# row = table[0]
447+
# row.fields('Name'..'NAME') # => ["Foo", "Bar"]
362448
#
449+
# Returns all fields if no argument given:
450+
# row.fields # => ["Foo", "Bar", "Baz"]
363451
def fields(*headers_and_or_indices)
364452
if headers_and_or_indices.empty? # return all fields--no arguments
365453
@row.map(&:last)

0 commit comments

Comments
 (0)