I am trying to get an array of hashes from parsing a CSV file using CSV
library.
I currently have this method which works:
def rows
rows = []
CSV.foreach(@csv_file.path, headers: true) do |row|
rows << row.to_hash
end
rows
end
but when I change it to this I get the stream closed
error.
def rows
CSV.foreach(@csv_file.path, headers: true).map(&:to_hash)
end
thanks
If you look at the source code of ::foreach
:
def self.foreach(path, options = Hash.new, &block)
encoding = options.delete(:encoding)
mode = "rb"
mode << ":#{encoding}" if encoding
open(path, mode, options) do |csv|
csv.each(&block)
end
end
It internally, opening the file using CSV::open
, with a block. So, once the block is closed, the IO
object got closed, internally. Now as you are trying to access the closed IO
object, you are getting the error.
From the doc of CSV::open
This method works like Ruby’s
open()
call, in that it will pass aCSV
object to a provided block and close it when the block terminates,...
The IO
object returned by ::foreach
is actually returned by the CSV::open
, within the method def self.foreach ...
.
Example :
2.1.0 :016 > require 'csv'
=> true
2.1.0 :017 > CSV.open("Gemfile")
=> <#CSV io_type:File io_path:"Gemfile" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
2.1.0 :018 > CSV.open("Gemfile") { |c| c }
=> <#CSV io_type:File io_path:"Gemfile" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
2.1.0 :019 > CSV.open("Gemfile") { |c| c }.read
IOError: closed stream
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With