So, I've been messing around with CSV files in Ruby, and I've come across an issue. In my testing, a call of x = CSV.read(file, headers:true) on a file which only contains the header row will return a table, that, when converted to an array, returns [], and calling x.headers returns . I can circumvent this problem by setting return_headers:true, but I don't actually want the file to return its headers, I just want the headers. When I add in a fake, second row, x.headers actually returns the headers, and :return_headers does not need to be set to true.
Here is some code from before and after adding a row to help visualize the issue.
With headers:true, return_headers:true on a csv file with only the header row:
a = CSV.read("June.csv", headers:true, return_headers:true) # <CSV::Table mode:col_or_row row_count:1>
a # <CSV::Row "Day":"Day" "Time":"Time">
a.headers # => ["Day", "Time"]
b = CSV.read("June.csv", headers:true) #<CSV::Table mode:col_or_row row_count:1>
b # => nil
b.headers # => 
c = CSV.read("June.csv", headers:true) #<CSV::Table mode:col_or_row row_count:2>
c.headers # => ["Day", "Time"]
c["Day"] # => ["6/1"]
The behavior you are experiencing is expected. A somewhat similar question two years ago had an answer that pointed out the same issue you're having. That person opened a bug report for Ruby where the Ruby devs responded and rejected it. And according to some people that is technically not a well-formed CSV.
However, I agree with you and the person who opened the bug. The
headers: true option should fill out the
CSV.headers regardless of whether there is actually data on the following lines or not. The current behavior seems baffling and will only lead to bugs in code.
As a quick fix for your issue I would simply pass
return_headers: true and begrudgingly skip over the first entry in the result, which will always be the header row.