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
を指定する場合と同じ動作をさせています。