@@ -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