@@ -358,17 +358,34 @@ def []=(*args)
358358
359359 #
360360 # :call-seq:
361- # <<( field )
362- # <<( header_and_field_array )
363- # <<( header_and_field_hash )
361+ # row << [header, value] -> self
362+ # row << hash -> self
363+ # row << value -> self
364364 #
365- # If a two-element Array is provided, it is assumed to be a header and field
366- # and the pair is appended. A Hash works the same way with the key being
367- # the header and the value being the field. Anything else is assumed to be
368- # a lone field which is appended with a +nil+ header.
365+ # Adds a field to +self+; returns +self+:
369366 #
370- # This method returns the row for chaining.
367+ # If the argument is a 2-element \Array <tt>[header, value]</tt>,
368+ # a field is added with the given +header+ and +value+:
369+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
370+ # table = CSV.parse(source, headers: true)
371+ # row = table[0]
372+ # row << ['NAME', 'Bat']
373+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
374+ #
375+ # If the argument is a \Hash, each <tt>key-value</tt> pair is added
376+ # as a field with header +key+ and value +value+.
377+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
378+ # table = CSV.parse(source, headers: true)
379+ # row = table[0]
380+ # row << {NAME: 'Bat', name: 'Bam'}
381+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
371382 #
383+ # Otherwise, the given +value+ is added as a field with no header.
384+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
385+ # table = CSV.parse(source, headers: true)
386+ # row = table[0]
387+ # row << 'Bag'
388+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
372389 def <<( arg )
373390 if arg . is_a? ( Array ) and arg . size == 2 # appending a header and name
374391 @row << arg
@@ -381,13 +398,15 @@ def <<(arg)
381398 self # for chaining
382399 end
383400
401+ # :call-seq:
402+ # row.push(*values) ->self
384403 #
385- # A shortcut for appending multiple fields. Equivalent to :
386- #
387- # args.each { |arg| csv_row << arg }
388- #
389- # This method returns the row for chaining.
390- #
404+ # Appends each of the given +values+ to +self+ as a field; returns +self+ :
405+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
406+ # table = CSV.parse(source, headers: true)
407+ # row = table[0]
408+ # row.push('Bat', 'Bam')
409+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
391410 def push ( *args )
392411 args . each { |arg | self << arg }
393412
@@ -396,14 +415,39 @@ def push(*args)
396415
397416 #
398417 # :call-seq:
399- # delete( header )
400- # delete( header, offset )
401- # delete( index )
418+ # delete(index) -> [header, value] or nil
419+ # delete(header) -> [header, value] or empty_array
420+ # delete(header, offset) -> [header, value] or empty_array
421+ #
422+ # Removes a specified field from +self+; returns the 2-element \Array
423+ # <tt>[header, value]</tt> if the field exists.
402424 #
403- # Removes a pair from the row by +header+ or +index+. The pair is
404- # located as described in CSV::Row.field(). The deleted pair is returned,
405- # or +nil+ if a pair could not be found.
425+ # If an \Integer argument +index+ is given,
426+ # removes and returns the field at offset +index+,
427+ # or returns +nil+ if the field does not exist:
428+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
429+ # table = CSV.parse(source, headers: true)
430+ # row = table[0]
431+ # row.delete(1) # => ["Name", "Bar"]
432+ # row.delete(50) # => nil
406433 #
434+ # Otherwise, if the single argument +header+ is given,
435+ # removes and returns the first-found field with the given header,
436+ # of returns a new empty \Array if the field does not exist:
437+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
438+ # table = CSV.parse(source, headers: true)
439+ # row = table[0]
440+ # row.delete('Name') # => ["Name", "Foo"]
441+ # row.delete('NAME') # => []
442+ #
443+ # If argument +header+ and \Integer argument +offset+ are given,
444+ # removes and returns the first-found field with the given header
445+ # whose +index+ is at least as large as +offset+:
446+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
447+ # table = CSV.parse(source, headers: true)
448+ # row = table[0]
449+ # row.delete('Name', 1) # => ["Name", "Bar"]
450+ # row.delete('NAME', 1) # => []
407451 def delete ( header_or_index , minimum_index = 0 )
408452 if header_or_index . is_a? Integer # by index
409453 @row . delete_at ( header_or_index )
@@ -414,15 +458,21 @@ def delete(header_or_index, minimum_index = 0)
414458 end
415459 end
416460
461+ # :call-seq:
462+ # row.delete_if {|header, value| ... } -> self
417463 #
418- # The provided +block+ is passed a header and field for each pair in the row
419- # and expected to return +true+ or +false+, depending on whether the pair
420- # should be deleted.
421- #
422- # This method returns the row for chaining.
464+ # Removes fields from +self+ as selected by the block; returns +self+.
423465 #
424- # If no block is given, an Enumerator is returned.
466+ # Removes each field for which the block returns a truthy value:
467+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
468+ # table = CSV.parse(source, headers: true)
469+ # row = table[0]
470+ # row.delete_if {|header, value| value.start_with?('B') } # => true
471+ # row # => #<CSV::Row "Name":"Foo">
472+ # row.delete_if {|header, value| header.start_with?('B') } # => false
425473 #
474+ # If no block is given, returns a new Enumerator:
475+ # row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
426476 def delete_if ( &block )
427477 return enum_for ( __method__ ) { size } unless block_given?
428478
@@ -431,14 +481,52 @@ def delete_if(&block)
431481 self # for chaining
432482 end
433483
484+ # :call-seq:
485+ # self.fields(*specifiers)
434486 #
435- # This method accepts any number of arguments which can be headers, indices,
436- # Ranges of either, or two-element Arrays containing a header and offset.
437- # Each argument will be replaced with a field lookup as described in
438- # CSV::Row.field().
487+ # Returns field values per the given +specifiers+, which may be any mixture of:
488+ # - \Integer index.
489+ # - \Range of \Integer indexes.
490+ # - 2-element \Array containing a header and offset.
491+ # - Header.
492+ # - \Range of headers.
439493 #
440- # If called with no arguments, all fields are returned.
494+ # For +specifier+ in one of the first four cases above,
495+ # returns the result of <tt>self.field(specifier)</tt>; see #field.
496+ #
497+ # Although there may be any number of +specifiers+,
498+ # the examples here will illustrate one at a time.
499+ #
500+ # When the specifier is an \Integer +index+,
501+ # returns <tt>self.field(index)</tt>L
502+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
503+ # table = CSV.parse(source, headers: true)
504+ # row = table[0]
505+ # row.fields(1) # => ["Bar"]
506+ #
507+ # When the specifier is a \Range of \Integers +range+,
508+ # returns <tt>self.field(range)</tt>:
509+ # row.fields(1..2) # => ["Bar", "Baz"]
510+ #
511+ # When the specifier is a 2-element \Array +array+,
512+ # returns <tt>self.field(array)</tt>L
513+ # row.fields('Name', 1) # => ["Foo", "Bar"]
514+ #
515+ # When the specifier is a header +header+,
516+ # returns <tt>self.field(header)</tt>L
517+ # row.fields('Name') # => ["Foo"]
518+ #
519+ # When the specifier is a \Range of headers +range+,
520+ # forms a new \Range +new_range+ from the indexes of
521+ # <tt>range.start</tt> and <tt>range.end</tt>,
522+ # and returns <tt>self.field(new_range)</tt>:
523+ # source = "Name,NAME,name\nFoo,Bar,Baz\n"
524+ # table = CSV.parse(source, headers: true)
525+ # row = table[0]
526+ # row.fields('Name'..'NAME') # => ["Foo", "Bar"]
441527 #
528+ # Returns all fields if no argument given:
529+ # row.fields # => ["Foo", "Bar", "Baz"]
442530 def fields ( *headers_and_or_indices )
443531 if headers_and_or_indices . empty? # return all fields--no arguments
444532 @row . map ( &:last )
0 commit comments