How to generate CSV files in Rails 12
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"
endHTML 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.csvYou get the point.

I’ve got a little ruby class that encapsulates to dumping of csv files out to disk. I use this to generate some regular reports.
It needs somework, to clean up the way reports are defined, but it works well.
That’s very nice.
How about making UsersController#index respond_to .csv instead of creating an entire action for it?
@Meekish – Good idea. That would be more Rails 2.0ish, wouldn’t it. Maybe I will post another example using respond_to soon.
@Meekish – Updated with a respond_to example.
Now that’s hot :)
Using Ruport:
Of course, maybe overkill if that’s all you need, but Ruport + acts_as_reportable also handles all associations and whatnot. (And uses FCSV under the hood)
Thanks Scott.
I’ve made this into a simple CSV Builder plugin to make this even easier.
Nice tool Joel. Very useful, thanks.
Would this work for those who must use version Rails 0.14.1? Also how would I call this in my view
thanks a lot. exactly what i needed, written clean and easy to copy. cheers, tim
Though this is a bit old it helped me get the basis for my time sheet going. This was very helpful, thanks for posting it.
This was very helpful thank you for posting it. I now have a csv I can use to create a time sheet. :)