【Rails】プルダウン検索編　ransackを導入して検索機能を作成する

#はじめに
保存したデータを項目事に分けて表示することで、欲しいデータのみ手に入れたい。
そんな時はransackです。

###目次
1. ランサック導入
2. ルーティング設定
3. モデル
4. コントローラー
5. ビュー
6. 重複の解消
7. 検索結果ページを作る


#開発環境
ruby 2.6.5
Rails 6.0.3.4
ransack 2.3.2

#1. ランサック導入

```:Ginfile
gem 'ransack'
```

```:ターミナル
bundle install
```





#2. ルーティング設定
今回は`demos`コントローラーを使用し、アクション名は`search`するので、`get 'demos/search'`を記述します。

```ruby:routes.rb
  root to: demos#index'
  resources :demos
  get 'demos/search' #ここransakuのルーティング
```


#3. モデル
今回は`demo`モデルとします。マイグレーションファイルを編集します。

```ruby:db/2020XXXXXXXXX_create_demos.rb
class CreateDemos < ActiveRecord::Migration[6.0]
  def change
    create_table :demos do |t|
      t.string     :sample_name
      t.string     :sample_kana
      t.string     :sample_email
      t.string     :sample_tel
      t.string     :sample_product_name
      t.string     :price
      t.integer    :num_id
      t.datetime   :start_time
      t.integer    :sample_id,             null: false

      t.timestamps
    end
  end
end
```
今回は上記の項目を保存します。

```:ターミナル
rails db:migrate
```


サンプルデータは自分で作成するか、「seed」を使います。
seedの使い方は下記の記事を参考にしてみてください。

【Rails】seedとFakerでランダムなサンプルデータを作成
https://qiita.com/AKI3/items/189574314ca94e8f43c6












#4. コントローラー

今回コントローラーは`demos`という名前です。

```ruby:app/controlers/demos_controller.rb
class DemosController < ApplicationController
  before_action :search_demo, only: [:index, :search]

  def index
    @demos = Demo.all
  end

  def search
    @results = @d.result
  end

  private

  def search_demo
    @d = Demo.ransack(params[:q])  # 検索オブジェクトを生成
  end
end
```

検索パラメーターのキーを「:q」とします。この「:q」とは「query（質問する）」のイニシャルのことです。

次に、`:q`を使って、demosテーブルから商品情報を探しています。そして、「@d」という名前の検索オブジェクトを生成しています。
この処理を行うメソッド名を「search_demo」としています。

最後にこの@dに対して「.result」とすることで、検索結果を取得しています。
これは、検索条件に該当した商品が@dに格納されているので、その格納されている値を表示する役割があります。



#5. ビュー
ビューに検索するバーを作成します。

```ruby:app/views/demos/index.html.erb
    <div class="search-data">
      <h3>商品検索</h3>
      <%= search_form_for @d, url: demos_search_path do |f| %>
        <%= f.label :sample_product_name_eq, '商品検索' %>
        <%= f.collection_select :sample_product_name_eq, @demo, :sample_product_name, :sample_product_name,  include_blank: '指定なし' %>
        <%= f.submit '検索' %>
      <% end %>
    </div>
```

まず、search_form_forの引数に「@d」を渡すことで検索フォームを生成します。
「_eq」は条件検索を行うための記述です。
続いて、<%= f.collection_select 第一引数, 第二引数, 第三引数, 第四引数, 第五引数, オプション %>の順で並んでいます。



できたらリロードしてプルダウンを確認します。










#ここを自分の言葉に編集

| 1 | 2 | 3 |
|:-:|:-:|:-:|
| 第一引数（メソッド名）  | :name_eq     |・カラム名・name属性やid属性を決める        |
| 第二引数（オブジェクト） |@demo       |配列データを指定する|（今回は商品データの配列）|
| 第三引数（value）    | name        |表示する際に参照するDBのカラム名           |
| 第四引数（name）     | name        |実際に表示されるカラム名                  |
|  オプション         |include_blank|何も選択していない時に表示される内容        |





#6. 重複の解消

このままだとこのように商品名が重複しています。
これを解消する為にコントローラーに以下を追記します。

```ruby:app/controlers/demos_controller.rb
#省略
  def index
    @demos = Demo.all
    set_demo_column #←追記
  end

#省略
private
  def set_demo_column
    @demo_date = Demo.select("sample_product_name").distinct  # 重複なくnameカラムのデータを取り出す
  end
```
html.erbも`@demo_date`に変更します。

```ruby:app/views/demos/index.html.erb
<%= f.collection_select :start_time_eq, @demo_date, :start_time, :start_time,  include_blank: '指定なし' %>
```












#7. 検索結果ページを作る
最後に検索ページを作成します。

```ruby:app/views/demos/search.html.erb
<h1>検索結果</h1>
<% if @results.length !=0 %>
  <% @results.each do |result| %>
    <td>
    <br>
    <li>
      <%= result.sample_name %>
      <%= result.sample_kana %>
      <%= result.sample_email %>
      <%= result.sample_tel %>
      <%= result.sample_product_name %>
      <%= result.price %>
      <%= result.num_id %>
      <%= result.start_time %>
      <%= result.created_at %>
    </li>
  <% end %>
<% else %>
  該当する商品はありません
<% end %>
<br>
<%= link_to 'トップページへ戻る', root_path %>
```

表示されれば完成です！

#まとめ
本記事では、RANSACKを導入してプルダウン検索機能を作成する方法を紹介しました。
今後別の検索機能も実装していきます。

###最後に
同じ様に悩んでる方々の助けになればと思い、記事を投稿しております。
それでは、また次回お会いしましょう〜





#参考
【公式】
https://github.com/activerecord-hackery/ransack