Rails

railsでcsv出力する時はviewで整形したほうがわかりやすくない?

More than 3 years have passed since last update.

railsでcsv出力したいときありますよね。

どういう方法でやろっかなーとザッとググってみたら、csv生成をcontroller内に直接書いたりModelにメソッド定義してModel.to_csv(records)みたいなかんじでやってるコードが結構出てきます。

けど、csvもhtmlやjsonなんかと同じようにviewで書いたほうがなんかスッキリする気がしたのでやってみました。


app/controllers/users_controller.rb

class UsersController < ApplicationController

def index
@users = User.all

respond_to do |format|
format.html do
@users = @users.page params[:page]
end
format.csv do
send_data render_to_string, filename: "users-#{Time.now.to_date.to_s}.csv", type: :csv
end
end
end
end



app/views/users/index.csv.ruby

require 'csv' # initializersとかに書いたほうがいいかも

CSV.generate do |csv|
cols = {
'ID' => ->(u){ u.id },
'姓名' => ->(u){ "#{u.last_name} #{u.first_name}" },
'性別' => ->(u){ u.sex },
'誕生日' => ->(u){ u.birthday.strftime('%Y年%m月%d日') },
'所持金' => ->(u){ number_to_currency u.money }
}

# header
csv << cols.keys

# body
@users.each do |user|
csv << cols.map{|k, col| col.call(user) }
end
end


# csvダウンロードへのリンクはこんなかんじで

= link_to 'Download CSV', users_path(format: :csv)

viewのテンプレートを.rubyとして素のrubyで書いて、controller側でrender_to_stringで文字列としてとってきてsend_dataでレスポンスとして投げつけてます。

controller側はformat.csvだけでも大丈夫なんですが、今回はファイル名を指定したかったのでこんなかんじに。

今回は標準ライブラリのCSVで書きましたが、テンプレートを素のrubyで書くので自分の好きなように書けるのはなかなかいいんでないかと。

あと、別の表示項目のcsvも必要だなーと思ったらその分view書いてから、action増やすなりrenderするview分けるなりでどんどん増やしやすい&Modelなんかに直接書くより見通しがいいんでないかと思います。


投稿してから、同様のものが既出だと気づいたけど、気にしないことにしました :stuck_out_tongue_closed_eyes: