Closed stream IO Error

I have made a CSV parser, and when I come to refactoring the rows method I am getting a closed stream error, can someone explain what I have done wrong please?

before the refactoring (this works):

class CSVParser
  def initialize(csv_file)
    @csv_file = csv_file
  end

  def rows
    rows = []

    CSV.foreach(@csv_file.path, headers: true) do |row|
      rows << row.to_hash
    end

    rows
  end
end

after re factoring(this is causing the error):

class CSVParser
  def initialize(csv_file)
    @csv_file = csv_file
  end

  def rows
    CSV.foreach(@csv_file.path, headers: true).map{|row| row.to_hash}
  end
end

Lets take a look at the source of #foreach - found here

def self.foreach(path, options = Hash.new, &block)
  open(path, options) do |csv|
    csv.each(&block)
  end
end

The enumerator is unfortunately locked within the open method. The open method returns nil which why you cannot call enumerable methods like you would expect (#map for example ).

I’ve run into this before and was super frustrated as well. Fortunately Ruby 2.1.0 seems to have changed the implementation. It will return an enumerator unless a block is provided.

def self.foreach(path, options = Hash.new, &block)
  return to_enum(__method__, path, options) unless block
  open(path, options) do |csv|
    csv.each(&block)
  end
end