Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in rails, how to return records as a csv file

I have a simple database table called "Entries":

class CreateEntries < ActiveRecord::Migration   def self.up     create_table :entries do |t|       t.string :firstName       t.string :lastName       #etc.       t.timestamps     end   end    def self.down     drop_table :entries   end end 

How do I write a handler that will return the contents of the Entries table as a CSV file (ideally in a way that it will automatically open in Excel)?

class EntriesController < ApplicationController    def getcsv     @entries = Entry.find( :all )      # ??? NOW WHAT ????    end  end 
like image 580
Eric Avatar asked Sep 18 '08 17:09

Eric


People also ask

Where should I put CSV in rails?

To me it made the most sense to place by CSV file in the lib folder in my Rails API project directory. You may place your file where it makes most sense to you. In Ruby, you can import your CSV file all at once (which stores all of the file content in memory) or read from the file one row at a time.


2 Answers

FasterCSV is definitely the way to go, but if you want to serve it directly from your Rails app, you'll want to set up some response headers, too.

I keep a method around to set up the filename and necessary headers:

def render_csv(filename = nil)   filename ||= params[:action]   filename += '.csv'    if request.env['HTTP_USER_AGENT'] =~ /msie/i     headers['Pragma'] = 'public'     headers["Content-type"] = "text/plain"      headers['Cache-Control'] = 'no-cache, must-revalidate, post-check=0, pre-check=0'     headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""      headers['Expires'] = "0"    else     headers["Content-Type"] ||= 'text/csv'     headers["Content-Disposition"] = "attachment; filename=\"#{filename}\""    end    render :layout => false end 

Using that makes it easy to have something like this in my controller:

respond_to do |wants|   wants.csv do     render_csv("users-#{Time.now.strftime("%Y%m%d")}")   end end 

And have a view that looks like this: (generate_csv is from FasterCSV)

UserID,Email,Password,ActivationURL,Messages <%= generate_csv do |csv|   @users.each do |user|     csv << [ user[:id], user[:email], user[:password], user[:url], user[:message] ]   end end %> 
like image 155
Clinton Dreisbach Avatar answered Sep 20 '22 21:09

Clinton Dreisbach


I accepted (and voted up!) @Brian's answer, for first pointing me to FasterCSV. Then when I googled to find the gem, I also found a fairly complete example at this wiki page. Putting them together, I settled on the following code.

By the way, the command to install the gem is: sudo gem install fastercsv (all lower case)

require 'fastercsv'  class EntriesController < ApplicationController    def getcsv       entries = Entry.find(:all)       csv_string = FasterCSV.generate do |csv|              csv << ["first","last"]             entries.each do |e|               csv << [e.firstName,e.lastName]             end           end           send_data csv_string, :type => "text/plain",             :filename=>"entries.csv",            :disposition => 'attachment'    end   end 
like image 28
Eric Avatar answered Sep 20 '22 21:09

Eric