railsにCSV形式でのダウンロード機能を追加する
背景
webアプリケーションの作成時に、「一覧データをExcelで開きたい」という要望をよく伺います。
そこで本記事ではrailsアプリにデータの一覧をcsv形式でダウンロード出来る機能を追加する方法について解説します。
モデルの変更
まずはモデルにCSV形式のデータを返却するメソッドを定義します。
今回は例として商品(Item)モデルを扱い、商品モデルは商品名と価格のカラムを持つということにします。
CSVファイルを扱うには、標準のCSVパッケージを使うのが簡単です。
ファイルサイズが巨大(例えば 100Mバイト以上)で無ければ性能的にも問題ないでしょう。
require 'csv'
class Item < ActiveRecord::Base
def self.to_csv
headers = %w(ID 商品名 価格 作成日時 更新日時)
csv_data = CSV.generate(headers: headers, write_headers: true, force_quotes: true) do |csv|
all.each do |row|
csv << row.attributes.values_at(*self.column_names)
end
end
csv_data.encode(Encoding::SJIS)
end
end
CSV生成時のオプションとして、headersおよびwrite_headersでヘッダー行書き込みを、force_quotesで全てのフィールドの作成時にクオートを追加することを指定しています。
また、Excelで開くことを想定して#encodeメソッドでShift JISの文字コードを指定しています。
コントローラーにformat指定を追加
次にコントローラーにCSV形式での返却指定を追加します
class ItemsController < ApplicationController
def index
@items = Item.all
respond_to do |format|
format.html
format.csv { send_data Item.to_csv, type: 'text/csv; charset=shift_jis', filename: "items.csv" }
end
end
respond_toブロック内部にformat.csvを追加することで、アドレス末尾に.csvを指定されたとき(例えばlocalhost:3000/items.csv)の動作を規定します。
CSV形式を指定した場合は直接ダウンロードさせたいので、send_dataを用いています。
ビューにダウンロードのリンクを張る
最後にダウンロード用のリンクを用意します。
= link_to 'CSV形式でダウンロード', items_path(format: 'csv')
コントローラーのindexメソッドにcsvでの返却を追加したのでitems_pathを指定し、そこにformat: 'csv'を渡すことでアドレス末尾に.csvを指定する場合と同じ動作をさせています。