Reputation: 115
I am reading a CSV file from a CDN and adding data to it then writing it back to a CDN for this reason I can't use append file.
I am also reordering the file which is why I have to turn it back into a CSV::Table
This code is a slimed down version of what I have but the problem is still replicated.
class SomeForm::Form
class << self
def add
data = CSV.parse(open(csv_file_url).read, headers: true)
data << ['david', 'smith'] # this will be dynamic
# data = data.sort_by { |row| [row['Firstname'], row['Lastname']] }
write_csv_file(CSV::Table.new(data).to_csv)
end
def csv_file_url
#somecode to get the file_url
end
def write_csv_file(data)
#somecode to write the file to the cdn
end
end
end
CSV file
Firstname,Lastname
So if I run SomeForm::Form.add with the csv file as above it outputs (removing the headers)
,
David,smith
However if the CSV file has at least one record in eg
Firstname,Lastname
Steve,Cougan
and run the code it adds the new record as expected
Firstname,Lastname
Steve,Cougan
david,smith
I would like to get this to work with csv with data in and csv with just the headers in.
As a aside this is for a rails3 project, though the above is replicatable in rails 5 as well
Thanks in advance
Upvotes: 0
Views: 1007
Reputation: 115
I have done some research following on from Chrisians answer.
And think this may be the problem https://github.com/ruby/csv/issues/75
Upvotes: 0
Reputation: 2187
I simplified the script but I can't really reproduce your issue.
data = CSV.parse("Firstname,Lastname", headers: true)
data << ['david', 'smith'] # this will be dynamic
data = data.sort_by { |row| [row['Firstname'], row['Lastname']] }
puts CSV::Table.new(data).to_csv
# Firstname,Lastname
# david,smith
However, if you still experience an issue I believe it might be the sorting. The CSV::Table
class is an enumerable but only iterates over the CSV rows without the headers (except in col
mode) so that means your sorting might just return an array of arrays without the header. When you now initialize the new CSV::Table
it will by default use the first row as the headers. Please note that you can access and set the headers as well like this.
data = CSV.parse("Firstname,Lastname", headers: true)
headers = data.headers
data << ['david', 'smith'] # this will be dynamic
data = data.sort_by { |row| [row['Firstname'], row['Lastname']] }
puts CSV::Table.new(data, headers: headers).to_csv
Here are the links to the implementation:
Upvotes: 1