Exporting to CSV with Rails

Exporting data to CSV is an excellent way to move your data out of a database and into a spreadsheet. The ability to export data from a Rails application is especially useful when you want to use it in another application or process.

The benefits of exporting your data include:

This post will discuss how to export data as a CSV from the Rails controller by using formats. First, set up the application and seed in some data.

1
2
3
4
5
rails new csv-export
bundle
rails db:create db:migrate
rails g scaffold Post title body:text author:string likes:integer comments:integer
rails db:migrate

Let’s put some data in:

1
2
3
4
5
6
7
# db/seeds.rb
Post.create(title: "Post 1", body: "This is the content of Post 1", author: "The first Author", likes: 1000, comments: 550)
Post.create(title: "Post 2", body: "This is the content of Post 2", author: "The second Author", likes: 2000, comments: 650)
Post.create(title: "Post 3", body: "This is the content of Post 3", author: "The third Author", likes: 3000, comments: 750)
Post.create(title: "Post 4", body: "This is the content of Post 4", author: "The forth Author", likes: 4000, comments: 850)
Post.create(title: "Post 5", body: "This is the content of Post 5", author: "The fifth Author", likes: 5000, comments: 950)
Post.create(title: "Post 6", body: "This is the content of Post 6", author: "The sixth Author", likes: 6000, comments: 1050)

Now, in post.rb, declare a method which will be responsible for generating data in CSV format. Depending upon your Rails version and the dependencies added, it’s possible you’ll need to add a require statement.

1
2
3
4
5
6
7
8
9
10
11
12
# app/models/post.rb

require 'csv'
def self.to_csv
 posts = all
 CSV.generate do |csv|
   csv << column_names
   posts.each do |post|
     csv << post.attributes.values_at(*column_names)
   end
 end
end

Next, update the index action in posts_controller.rb like below:

1
2
3
4
5
6
7
8
9
# app/controllers/posts_controller.rb

def index
 @posts = Post.all
 respond_to do |format|
   format.html
   format.csv { send_data Post.to_csv, filename: "posts-#{DateTime.now.strftime("%d%m%Y%H%M")}.csv"}
 end
end

Lastly, in posts/index.html.erb, add a button like this:

1
2
3
# app/views/posts/index.html.erb

<%= link_to "Export", posts_path(format: 'csv') %>

Now a CSV file will be generated and downloaded on the system. Happy exporting!