[Ruby on Rails 5] Exporting Ransack results to CSV in Rails 5.1

Ransack の導入について、かんたんにまとめておきます。

[markdown]

“`prettyprinted
Rails 5.1.4
ransack 1.8.6
“`

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

> * [activerecord-hackery/ransack: Object-based searching.](https://github.com/activerecord-hackery/ransack)
> * [Railsでransackを使って検索機能を作成する – Rails Webook](http://ruby-rails.hatenadiary.com/entry/20141008/1412774436)
> * [#370 Ransack – RailsCasts](http://railscasts.com/episodes/370-ransack)

## rails generate

省略。下記の続きです。
正確には、この記事では TSV 出力を実装しています。

> * [[Ruby on Rails 5] Exporting records to TSV in Rails 5.1 | deadwood](https://www.d-wood.com/blog/2018/01/26_9443.html)

## Installation

`bundle install` します。

“`ruby:Gemfile
gem ‘ransack’
“`

## Search form

インデックスページにサーチフォームを追加します。

### Controller

“`ruby:app/controllers/data_controller.rb
class DataController < ApplicationController # GET /data # GET /data.tsv def index @q = Datum.ransack(params[:q]) @data = @q.result(distinct: true) respond_to do |format| format.html format.tsv { send_data @data.to_csv(col_sep: "\t"), filename: "data-#{Time.zone.now.strftime('%d%m%Y%H%M')}.tsv" } end end ``` `result` > resutはActiveRecord::Relationを返すので、SQLは普通のActiveRecord同様遅延評価されますし、さらにwhereを繋げたり、kaminariでページングしたりすることもできます。また、to_sqlで発行されるSQLを確認することもできます。
>
> [Ransackのススメ – Qiita](https://qiita.com/nysalor/items/9a95d91f2b97a08b96b0)

`distinct: true`

> * [activerecord-hackery/ransack: Object-based searching.](https://github.com/activerecord-hackery/ransack#problem-with-distinct-selects)

### View

`search_form_for` ヘルパーを利用します。
Haml と [Bootstrap v4](https://getbootstrap.com/docs/4.0/components/forms/) でスタイリングすると、下記のようになります。

“`ruby:app/views/data/index.html.haml
= search_form_for(@q, class: ‘form-inline’) do |f|
.form-group
= f.label :title_or_filename_cont
= f.search_field :title_or_filename_cont, class: ‘form-control mx-sm-3 mb-2’
= f.submit ‘Submit’, class: ‘btn btn-primary mb-2’
“`

検索条件の指定には、`_or_` や `_cont` のような [Search Matchers](https://github.com/activerecord-hackery/ransack#search-matchers) を利用します。

## CSV download

ダウンロードボタンを追加します。

### View

Ransack の検索結果には、以下のようなパラメータが渡っていました。

“`ruby
{“utf8″=>”✓”, “q”=>{“title_or_filename_cont”=>”tex”}, “commit”=>”Submit”, “controller”=>”data”, “action”=>”index”}
“`

検索結果をダウンロードさせるには、`link_to` にパラメータが渡るように修正(`q: request.params[:q]`)します。

> * [Railsのlink_toにパラメータを追加する – Rails Webook](http://ruby-rails.hatenadiary.com/entry/20150114/1421161200)

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

## Sort link

テーブルのタイトルクリックで、昇順や降順表示をさせます。

### View

`sort_link` ヘルパーを利用します。
このままで表示順も CSV download に反映されます。

“`ruby:app/views/data/index.html.haml
.table-responsive
%table.table.table-striped
%thead
%tr
%th= sort_link(@q, :depth)
%th= sort_link(@q, :title)
%th= sort_link(@q, :filename, ‘Filename’, default_order: :desc)
%th Description
%th Keywords
%th Content 1
%th Content 2
%th
%th
%th
%tbody
– @data.each do |datum|
“`

[/markdown]