LoginSignup
71
62

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-09-22

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:

71
62
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
62