使用Ruby中的Tempfile写入文件

7

我有一个后台任务,将数据写入CSV文件并通过电子邮件发送给用户。我使用Tempfile类,所以在将文件发送至用户后会将其删除。目前,当我查看生成的CSV文件时,结果如下:

["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"]

请忽略数据,但问题在于,它以ruby格式直接写入文件,并且没有删除""和[]字符。
请查看以下代码:
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

这是否与使用tempfile类而不是csv类有关?或者我能否做些改变以改变写入文件的方式?
在邮件程序中添加读取csv文件的代码。我目前收到一个类型错误,提示“无法将CSV转换为字符串”。
class ReportMailer < ActionMailer::Base
 default :from => "test@gmail.com"

  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

请看https://dev59.com/mGYq5IYBdhLWcg3wbgHk#14490012 - Dennis
4个回答

15

问题是您实际上没有将csv数据写入文件中。您正在向文件句柄发送数组。我认为您需要类似以下的内容:

Tempfile.open(....) do |fh|
    csv = CSV.new(fh, ...)
    <rest of your code>
end

正确设置CSV输出过滤。


谢谢!你知道从一个<#CSV io_type:Tempfile对象读取的正确方法吗?我目前尝试从中读取时遇到了TypeError:无法将CSV转换为字符串... - BC00
你能给我展示那段代码吗?如果你正在从刚写入的句柄中读取,请不要忘记倒回句柄(或使用seek()函数将其定位到开头)。否则,你将尝试从EOF处读取。 - Dave S.
如果你只是要读取CSV文件,为什么还要在这里写入它呢?你可以直接将CSV writer指向一个stringio对象,然后邮件程序就可以直接分配它。 - Dave S.

6

以下是我是如何做到的。

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

3

我更喜欢做

tempfile = Tempfile.new(....)
csv = CSV.new(tempfile, ...) do |row|
  <rest of your code>
end

1

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接