如何生成CSV文件?

use*_*621 6 ruby csv action ruby-on-rails

我正在尝试使用数据库中的数据生成CSV输出.我想将这些数据提供给第三方,所以我想我会给某人一个URL(website.com/api_data/cars)并通过访问这个URL,这个人就可以使用它了 - 我想我想要访问URL然后去看到(在动作中)数据显示并用,或分隔;.

但是怎么做呢?

到目前为止,我正在尝试以下方法:

csv_string = CSV.generate do |csv|
  cols = ["column one", "column two", "column three"]
  csv << cols
  csv << ["A", "B", "C"]

  @filename = "data-#{Time.now.to_date.to_s}.csv"  
end
send_data(csv_string, :type => 'text/csv; charset=utf-8; header=present', :filename => @filename)  
Run Code Online (Sandbox Code Playgroud)

这是在控制器generate_data和action csv_cars中.

当我运行此操作(webste.com/generate_data/csv_cars)时,它会自动弹出一个窗口来下载文件.

但是如何将CSV内容写入动作?所以当我打开URL时,我会看到那里写的数据库中的内容?

小智 13

我知道这是一个老线程,但我在搜索中遇到了它,以防其他人也这样做,这是我的回答以及对我有用的东西.

我认为bhanu有一个很好的方法,但我确实改变了一些东西.我没有在respond_to中执行@cars,而是调用了send_data Cars.to_csv,因为正如Rob所说,它是作为一个类方法而制作的.它对我来说很漂亮.

class Car < ActiveRecord::Base
  def self.to_csv(make)
    attributes = %w{id name price} #customize columns here
    cars = Car.where(maker_name: make)

    CSV.generate(headers: true) do |csv|
      csv << attributes

      cars.each do |car|
        csv << attributes.map{ |attr| car.send(attr) }
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后在控制器中

class CarsController < ApplicationController
  def index
    send_data Cars.to_csv('Chevy'), filename: "cars-#{Date.today}.csv"
  end
end
Run Code Online (Sandbox Code Playgroud)

我知道当你去汽车/索引时会调用它,但是你可以将它放入任何方法,如果声明或任何你想要的东西,只要你想从那里调用它.你也可以有参数,就像我上面用make做的那样,并查询某些字段.这绝对比我想象的容易得多.希望这有助于某人.


bha*_*anu 6

在模型中定义 to_csv 方法,如下所示

class Car < ActiveRecord::Base
  def self.to_csv
    attributes = %w{id name price} #customize columns here

    CSV.generate(headers: true) do |csv|
      csv << attributes

      all.each do |car|
        csv << attributes.map{ |attr| car.send(attr) }
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

稍后在你的控制器中

class CarsController < ApplicationController
  def index
    @cars = Car.all

    respond_to do |format|
      format.html
      format.csv { send_data @cars.to_csv, filename: "cars-#{Date.today}.csv" }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)


Nee*_*mar 5

你需要做这样的事情。

def csv_cars
  headers = ['column one', 'column two', 'column three']

  csv_data = CSV.generate(headers: true) do |csv|
    csv << headers
    csv << ["A", "B", "C"]
  end

  send_data csv_data, filename: "data-#{Date.today.to_s}.csv", disposition: :attachment
end
Run Code Online (Sandbox Code Playgroud)