14

I want to give my users the ability to export a table to CSV.

So in my controller, I've added on top of the file:

  respond_to :html, :js, :csv

I'm also setting the headers if the requested format is csv:

if params[:format] == 'csv'
  generate_csv_headers("negotiations-#{Time.now.strftime("%Y%m%d")}") 
end

Code for generate_csv_headers(in application_controller) is:

  def generate_csv_headers(filename)
    headers.merge!({
      'Cache-Control'             => 'must-revalidate, post-check=0, pre-check=0',
      'Content-Type'              => 'text/csv',
      'Content-Disposition'       => "attachment; filename=\"#{filename}\"",
      'Content-Transfer-Encoding' => 'binary'
    })
  end

I've also created a view named index.csv.erb to generate my file:

<%- headers = ["Id", "Name"] -%>
<%= CSV.generate_line headers %>
<%- @negotiations.each do |n| -%>
<%- row = [ n.id,
            n.name ] -%>
<%=   CSV.generate_line row %>
<%- end -%>

I don't have any error, but it simply displays the content of the CSV file, while I'd expect a prompt from the browser to download the file.

I've read a lot, but could not find anything that'd work. Do you have an idea?

thanks, p.

Pierre
  • 8,368
  • 4
  • 34
  • 50
  • Some good discussion on this topic in [this SO thread](http://stackoverflow.com/questions/94502/in-rails-how-to-return-records-as-a-csv-file) – zetetic Jan 03 '11 at 23:48

3 Answers3

10

I'm still unsure about why this fixed the issue, but it did.

I changed the link in the view to

<%= link_to "Export to csv", request.parameters.merge({:format => :csv})%>

and it now works!

Pierre
  • 8,368
  • 4
  • 34
  • 50
0

You might be interested in this gem I made called CSV shaper that allows you to create CSV output using a really nice Ruby DSL.

It will also handle setting the response headers correctly, while allowing filename customisaton.

https://github.com/paulspringett/csv_shaper

paul
  • 307
  • 2
  • 4
0

I'm not sure you have to do it this way, but if you generate and save the file, you can use send_file to send it to the browser. See http://api.rubyonrails.org/classes/ActionController/Streaming.html

Gunner
  • 347
  • 3
  • 10
  • 2 things: I'm generating data on the fly and I'm note sure that I can't write file (I'm on Heroku). – Pierre Jan 04 '11 at 06:30