Writing to a file via Tempfile in Ruby
Solution 1
The issue is that you're not actually writing csv data to the file. You're sending arrays to the filehandle. I believe you need something like:
Tempfile.open(....) do |fh|
csv = CSV.new(fh, ...)
<rest of your code>
end
to properly setup the CSV output filtering.
Solution 2
I prefer to do
tempfile = Tempfile.new(....)
csv = CSV.new(tempfile, ...) do |row|
<rest of your code>
end
Solution 3
Here's how I did it.
patient_payments = PatientPayment.all
Tempfile.new(['patient_payments', '.csv']).tap do |file|
CSV.open(file, 'wb') do |csv|
csv << patient_payments.first.class.attribute_names
patient_payments.each do |patient_payment|
csv << patient_payment.attributes.values
end
end
end
Solution 4
try this:
Tempfile.open(["#{Rails.root}/tmp/", ".csv"]) do |outfile|
CSV::Writer.generate(outfile) do |csv|
csv << ["Application", "Price", "Tax", "Credit", "Base Price", "Billed At", "Order ID", "Payment ID", "Payment Type"]
#...
end
end
BC00
Updated on June 17, 2022Comments
-
BC00 almost 2 years
I have the below background job that writes to a csv file and emails it out. I am using the Tempfile class so the file is removed after I email it to the user. Currently, when I look at the csv file I am producing the results look like the following:
["Client Application" "Final Price" "Tax" "Credit" "Base Price" "Billed At" "Order Guid" "Method of Payment Guid" "Method of Payment Type"] ["web" nil nil nil nil nil nil "k32k313k1j3" "credit card"]
Please ignore the data, but the issue is, it is being written directly to the file in the ruby format and not removing the "" and [] characters.
Please see the code below:
class ReportJob @queue = :report_job def self.perform(client_app_id, current_user_id) user = User.find(current_user_id) client_application = Application.find(client_app_id) transactions = client_application.transactions file = Tempfile.open(["#{Rails.root}/tmp/", ".csv"]) do |csv| begin csv << ["Application", "Price", "Tax", "Credit", "Base Price", "Billed At", "Order ID", "Payment ID", "Payment Type"] transactions.each do |transaction| csv << "\n" csv << [application.name, transaction.price, transaction.tax, transaction.credit, transaction.base_price, transaction.billed_at, transaction.order_id, transaction.payment_id, transaction.payment_type] end ensure ReportMailer.send_rev_report(user.email, csv).deliver csv.close(unlink_now=false) end end end end
Would this be an issue with using the tempfile class instead of the csv class? or is there something I could do to change the way it is being written to the file?
Adding the code for reading the csv file in the mailer. I am currently getting a TypeError that says "can't convert CSV into String".
class ReportMailer < ActionMailer::Base default :from => "[email protected]" def send_rev_report(email, file) attachments['report.csv'] = File.read("#{::Rails.root.join('tmp', file)}") mail(:to => email, :subject => "Attached is your report") end end end
-
BC00 over 11 yearsThank You! Would you know the proper way to read from an <#CSV io_type:Tempfile object? I am currently getting a TypeError: can't convert CSV into String when trying to read from it...
-
Dave S. over 11 yearsCan you show me the code for that piece? If you're reading from the same handle as you just wrote to - don't forget to rewind the handle (or seek() to the beginning). Otherwise you'll be trying to read from EOF.
-
Dave S. over 11 yearsWhy bother writing the CSV file here if you're just going to read it back in? You may as well just point the CSV writer at a stringio object and then the mailer can just assign that directly.