Rails4からRubyテンプレートが追加されました。
hoge.csv.rubyというようなファイルを用意することで、hoge.html.erbと同じような感覚でrubyスクリプトでViewが書けます。
環境
- OS: Windows10 64bit, Rails version: 4.2.1, Ruby version: 2.1.6-p336 (x64-mingw32)
-
rails g scaffold User name:string email:string
した直後の状態 -
ja.yml
でカラム名を日本語化済み
要件
-
http://localhost:3000/users
にアクセスするとユーザー一覧が表示できる状態で、http://localhost:3000/users.csv
にアクセスすると、ユーザー一覧のCSVファイルusers.csv
がダウンロードできる。 - CSVのカラムはnameとemailで、ヘッダーのカラム名は日本語
- Windows環境で文字化けしないように文字コードはShift_JISで。
コード
/app/views/users/index.csv.ruby
require 'kconv'
columns = [:name, :email]
res = ""
res << columns.map{|c| User.human_attribute_name c }.join(',')+"\r" # header
@users.pluck(*columns).each do |u|
res << u.join(',')+"\r" # body
end
res.tosjis
# もしくは
require 'kconv'
require 'csv'
columns = [:name, :email]
CSV.generate do |csv|
csv << columns.map{|c| User.human_attribute_name c } # header
@users.pluck(*columns).each{|u| csv << u } # body
end.tosjis
/app/controllers/users_controller.rb
# 抜粋です。scaffold直後から変更なし。respond_toかかなくてもOK
class UsersController < ApplicationController
def index
@users = User.all
respond_to do |format|
format.html
format.csv do
filename = 'users'
headers['Content-Disposition'] = "attachment; filename=\"#{filename}.csv\""
end
end
end end
end
/app/views/users/index.html.erb
# お好きなところにリンクをどうぞ。
<%= link_to 'csv download', users_path(format: :csv) %>
メリット
- CSVの整形に関するコードをModelやControllerに書かなくてスッキリ!
デメリット
- 例えば、テンプレートのCSVをダウンロードし、それを編集した後にアップロードする、というフローがあるとする。テンプレートCSVのカラムとアップロードされたCSVのカラムがずれていないことをチェックする、という要件がある場合、使いにくい。カラムの列整形にかかわるコードが、View(index.csv.ruby)とView以外(UsersControllerかUserモデル)に分かれてしまい、メリットが無くなる。
-
ファイル名を動的に変更できない。"URLの最後のスラッシュ以下".csv というファイル名になる。レスポンスヘッダの Content-Disposition でファイル名を指定すればOK(上記参照)。send_data filename: hoge.csv
を使えばよいが、他に良い方法があれば教えて下さい。