Skip to content

Commit

Permalink
* lib/csv.rb (CSV::{Row,Table}#{each,delete_if}): returns an enumerator
Browse files Browse the repository at this point in the history
  if no block is given. [ruby-core:75346] [Feature #11058]

* test/csv/test_row.rb: add test for above.

* test/csv/test_table.rb: ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56083 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
k-tsj committed Sep 7, 2016
1 parent f60caf1 commit b425d4f
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
9 changes: 9 additions & 0 deletions ChangeLog
@@ -1,3 +1,12 @@
Wed Sep 7 14:56:59 2016 Kazuki Tsujimoto <kazuki@callcc.net>

* lib/csv.rb (CSV::{Row,Table}#{each,delete_if}): returns an enumerator
if no block is given. [ruby-core:75346] [Feature #11058]

* test/csv/test_row.rb: add test for above.

* test/csv/test_table.rb: ditto.

Wed Sep 7 14:50:01 2016 Kazuki Tsujimoto <kazuki@callcc.net>

* gems/bundled_gems: update to power_assert 0.3.1.
Expand Down
20 changes: 17 additions & 3 deletions lib/csv.rb
Expand Up @@ -431,7 +431,11 @@ def delete(header_or_index, minimum_index = 0)
#
# This method returns the row for chaining.
#
# If no block is given, an Enumerator is returned.
#
def delete_if(&block)
block or return enum_for(__method__) { size }

@row.delete_if(&block)

self # for chaining
Expand Down Expand Up @@ -500,13 +504,15 @@ def field?(data)

#
# Yields each pair of the row as header and field tuples (much like
# iterating over a Hash).
# iterating over a Hash). This method returns the row for chaining.
#
# Support for Enumerable.
# If no block is given, an Enumerator is returned.
#
# This method returns the row for chaining.
# Support for Enumerable.
#
def each(&block)
block or return enum_for(__method__) { size }

@row.each(&block)

self # for chaining
Expand Down Expand Up @@ -822,7 +828,11 @@ def delete(index_or_header)
#
# This method returns the table for chaining.
#
# If no block is given, an Enumerator is returned.
#
def delete_if(&block)
block or return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size }

if @mode == :row or @mode == :col_or_row # by index
@table.delete_if(&block)
else # by header
Expand All @@ -845,7 +855,11 @@ def delete_if(&block)
#
# This method returns the table for chaining.
#
# If no block is given, an Enumerator is returned.
#
def each(&block)
block or return enum_for(__method__) { @mode == :col ? headers.size : size }

if @mode == :col
headers.each { |header| block[[header, self[header]]] }
else
Expand Down
25 changes: 23 additions & 2 deletions test/csv/test_row.rb
Expand Up @@ -209,9 +209,20 @@ def test_delete
# by header
assert_equal(["C", 3], @row.delete("C"))

# using a block
end

def test_delete_if
assert_equal(@row, @row.delete_if { |h, f| h == "A" and not f.nil? })
assert_equal([["A", nil]], @row.to_a)
assert_equal([["B", 2], ["C", 3], ["A", nil]], @row.to_a)
end

def test_delete_if_without_block
enum = @row.delete_if
assert_instance_of(Enumerator, enum)
assert_equal(@row.size, enum.size)

assert_equal(@row, enum.each { |h, f| h == "A" and not f.nil? })
assert_equal([["B", 2], ["C", 3], ["A", nil]], @row.to_a)
end

def test_fields
Expand Down Expand Up @@ -281,6 +292,16 @@ def test_each

# verify that we can chain the call
assert_equal(@row, @row.each { })

# without block
ary = @row.to_a
enum = @row.each
assert_instance_of(Enumerator, enum)
assert_equal(@row.size, enum.size)
enum.each do |pair|
assert_equal(ary.first.first, pair.first)
assert_equal(ary.shift.last, pair.last)
end
end

def test_enumerable
Expand Down
59 changes: 59 additions & 0 deletions test/csv/test_table.rb
Expand Up @@ -220,6 +220,17 @@ def test_each
# verify that we can chain the call
assert_equal(@table, @table.each { })

# without block
enum = @table.each
assert_instance_of(Enumerator, enum)
assert_equal(@table.size, enum.size)

i = 0
enum.each do |row|
assert_equal(@rows[i], row)
i += 1
end

###################
### Column Mode ###
###################
Expand All @@ -231,6 +242,17 @@ def test_each
assert_equal(@table[header], column)
end

# without block
enum = @table.each
assert_instance_of(Enumerator, enum)
assert_equal(@table.headers.size, enum.size)

headers = @table.headers
enum.each do |header, column|
assert_equal(headers.shift, header)
assert_equal(@table[header], column)
end

############################
### One Shot Mode Change ###
############################
Expand Down Expand Up @@ -363,6 +385,24 @@ def test_delete_if_row
END_RESULT
end

def test_delete_if_row_without_block
######################
### Mixed/Row Mode ###
######################
enum = @table.delete_if
assert_instance_of(Enumerator, enum)
assert_equal(@table.size, enum.size)

# verify that we can chain the call
assert_equal(@table, enum.each { |row| (row["B"] % 2).zero? })

# verify resulting table
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
A,B,C
4,5,6
END_RESULT
end

def test_delete_if_column
###################
### Column Mode ###
Expand All @@ -378,6 +418,25 @@ def test_delete_if_column
END_RESULT
end

def test_delete_if_column_without_block
###################
### Column Mode ###
###################
@table.by_col!

enum = @table.delete_if
assert_instance_of(Enumerator, enum)
assert_equal(@table.headers.size, enum.size)

assert_equal(@table, enum.each { |h, v| h > "A" })
assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
A
1
4
7
END_RESULT
end

def test_values_at
##################
### Mixed Mode ###
Expand Down

0 comments on commit b425d4f

Please sign in to comment.