How to generate CSV files in Rails
A while back someone posted on rubyonrails-talk asking how to export to CSV from Rails. I posted a solution, and people seemed to dig it, so I’ll share it again here.
Use FasterCSV
Get the FasterCSV gem. Why? It’s faster, and easier to use. Once you’ve got it, require it in environment.rb. Here’s an abbreviated version of my working controller method. Copy/paste/modify. And you’re done!
def export_to_csv
@users = User.find(:all)
csv_string = FasterCSV.generate do |csv|
# header row
csv << ["id", "first_name", "last_name"]
# data rows
@users.each do |user|
csv << [user.id, user.first_name, user.last_name]
end
end
# send it to the browsah
send_data csv_string,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=users.csv"
end
HTML or CSV, have it your way
Now, if we wanted to get all clever about it, we could go further and serve both html and CSV data with only one action, using respond_to. This also requires that you add a RESTful route (map.resources :users) to your routes.rb file:
def index
@users = User.find(:all)
respond_to do |wants|
wants.html
wants.csv do
csv_string = FasterCSV.generate do |csv|
# header row
csv << ["id", "first_name", "last_name"]
# data rows
@users.each do |user|
csv << [user.id, user.first_name, user.last_name]
end
end
# send it to the browsah
send_data csv_string,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=users.csv"
end
end
end
Now if the user requests:
/users
she’ll get HTML. If she requests:
/users.csv
You get the point.