RailsアプリにCSVエクスポート機能を追加したい!

こんにちは!kossyです!




本日気になったニュースはこちら
thebridge.jp

採用に関する労力や費用を抑えられそうな気がします。

某プログラミングスクールの例だと、転職斡旋に成功した場合は、
転職者の年収の3-4割がスクールの報酬となるらしく、
扱う人材が未経験という点を考えると、優秀とされている人材を
業界の水準よりも安い手数料で雇用できるのはいい点だと思います。

ただ、優秀な人材は無尽蔵に現れるとは思えないですし、
そもそもどうやって優秀な人材を集めているのか、等が気になりますね。

本元のプレスリリースはこちら
VCが投資先スタートアップのダイレクトリクルーティングを直接行う『VCテラス』のサービス提供開始|株式会社アマテラス のプレスリリース











さて、今回は、RailsアプリケーションのCSVエクスポート機能の実装方法を
ブログに残してみたいと思います。




環境
Rails 5.2.1
Ruby 2.5.1
MacOS Mojave





任意のモデルにメソッドを追記

任意のモデルファイル(ここではContentとしています)
class Content < ApplicationRecord

  def self.csv_attributes
    ["name", "content", "created_at", "updated_at"]
  end

  def self.generate_csv
    CSV.generate(headers: true) do |csv|
      csv << csv_attributes
      all.each do |cont|
        csv << csv_attributes.map{|attr| cont.send(attr)}
      end
    end
  end

end

csv_attributesメソッドは、CSVファイルにどの順番で出力するかを定義しています。

csv.generateでCSVデータの文字列を生成し、
csv << csv_attributesの行でヘッダを出力しています。

その後allメソッドでContentモデルのレコードを全て取得し、
カラムごとにContentモデルからデータを取り出してCSVに抽出しています。



コントローラの実装

app/controllers/contents_controller.rb

省略

def index
  @contents = Contents.all.order(created_at: :DESC)

  respond_to do |format|
    format.html
    format.csv { send_data @contents.generate_csv, filename: "contents-#{Time.zone.now.strftime('%Y%m%d%S)}.csv"}
  end
end

省略

respond_toでリクエストに応じて出力のフォーマットを分けるように実装します。
format.htmlでhtml形式のリクエストがあった場合、
format.csvcsv形式でのリクエストがあった場合、
という風に処理を分けています。

csvフォーマットでのリクエストが来た場合は、send_dataメソッドを使って、レスポンスを送り出し、
ブラウザからCSVファイルとしてダウンロードできるようにしています。

後はapp/views/contents/index.html.haml(hamlで記述しています)にlink_toメソッドでcsv抽出のボタンを作成します。

app/views/contents/index.html.haml

任意の場所に以下を記述
= link_to 'エクスポート' contents_path(format: :csv), class: 'btn btn-primary'

パスは名前付きパスを使用し、引数にformat: :csvを指定することで、csv形式でのリクエストを送ることができます。