[Ruby on Rails 5] Exporting records to TSV in Rails 5.1

MIME type の追加など、手順を忘れていたので記事に起こしておきます。

[markdown]

“`prettyprinted
% rails –version
Rails 5.1.4
“`

こちらを参考にさせて頂きました。

> * [RailsでCSV/Excelのダウンロード機能の実装方法 – Rails Webook](http://ruby-rails.hatenadiary.com/entry/20141119/1416398472)
> * [#362 Exporting CSV and Excel – RailsCasts](http://railscasts.com/episodes/362-exporting-csv-and-excel)
> * [https://rubyplus.com/articles/4121-Exporting-Records-in-CSV-and-Excel-Formats-in-Rails-5](https://rubyplus.com/articles/4121-Exporting-Records-in-CSV-and-Excel-Formats-in-Rails-5)

## rails generate

省略。
`rails g` でこのようなプロジェクトを作成してあります。

“`db/schema.rb
ActiveRecord::Schema.define(version: 20180118080513) do
create_table “data”, force: :cascade, options: “ENGINE=InnoDB DEFAULT CHARSET=utf8” do |t|
t.integer “depth”
t.string “title”
t.string “filename”
t.text “description”
t.string “keywords”
t.text “content_1”
t.text “content_2”
t.datetime “created_at”, null: false
t.datetime “updated_at”, null: false
end
end
“`

## TSV Download

TSV は `CSV.generate(col_sep: “\t”)` で作成します。

> * [[Ruby] Rubyでヘッダ付きのCSVを生成する | deadwood](https://www.d-wood.com/blog/2015/11/14_7685.html)

### View

ダウンロードボタンをビューの一覧に追加します。

“`ruby:views/data/index.html.haml
.btn-group
= link_to ‘Download TSV’, data_path(format: ‘tsv’), class: ‘btn btn-primary’
“`

### Controller

[respond_to](http://railsdoc.com/references/respond_to) を利用して、フォーマットに応じた出力をコントローラで指定します。

“`ruby:controllers/data_controller.rb
class DataController < ApplicationController # GET /data # GET /data.json # GET /data.tsv def index @data = Datum.all respond_to do |format| format.html format.json { render json: @data } format.tsv { send_data @data.to_csv(col_sep: "\t") } end end end ``` ### Model モデルに `to_csv` メソッドを用意します。 ```ruby:models/datum.rb class Datum < ApplicationRecord def self.to_csv(options = {}) CSV.generate(options) do |csv| csv << column_names all.each do |data| csv << data.attributes.values_at(*column_names) end end end end ``` ### Config `require 'csv'` をします。 ```ruby:config/application.rb require 'csv' ``` また未設定の場合、下記のようなエラーが表示されて、[Rails Guides](http://guides.rubyonrails.org/action_controller_overview.html#restful-downloads) を見て MIME type を登録してね、と言われます。 ```prettyprinted To respond to a custom format, register it as a MIME type first: http://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. If you meant to respond to a variant like :tablet or :phone, not a custom format, be sure to nest your variant response within a format response: format.html { |html| html.tablet { ... } } ``` MIME type も追加しておきます。 > * [https://www.iana.org/assignments/media-types/text/tab-separated-values](https://www.iana.org/assignments/media-types/text/tab-separated-values)
> * [Media Types](https://www.iana.org/assignments/media-types/media-types.xhtml)

“`ruby:config/initializers/mime_types.rb
Mime::Type.register ‘text/tab-separated-values’, :tsv
“`

サーバを再起動するとダウンロードが可能になります。

## 補遺

View を用意するパターン。

> * [RailsでMVCを意識してシンプルにCSV出力 – Qiita](https://qiita.com/necojackarc/items/39e0f0c438363f7084db)
「Railsプロジェクトの作成」部分のメモ。
> * [RailsでCSV/Excelのダウンロード機能の実装方法 – Rails Webook](http://ruby-rails.hatenadiary.com/entry/20141119/1416398472)

“`ruby
# app/models/manufacture.rb
class Manufacture < ActiveRecord::Base has_many :products end # app/contollers/products_contoller.rb class ProductsController < ApplicationController def index # N+1問題のため、allではなくincludes @products = Product.includes(:manufacture) end end # app/models/product.rb class Product < ActiveRecord::Base belongs_to :manufacture end ``` [/markdown]