【Rails】ransackとkaminariを利用した検索フォームの実装方法

# 概要
* Railsにて検索フォームを設けたので、その手順をここに整理する。

# 前提
* ユーザーは検索フォームに任意のitemをひらがな入力することで、該当のものを探すことができる（検索対象のデータはあらかじめひらがなのカラムを用意しておく）
* 検索結果が該当しない場合は、「該当するxxxxxはありません」というメッセージが表示される。
　例：items/?utf8=✓&search=あああああ
* 検索機能はRansackを導入することで実装する。
* 検索時に一括で全表示されると1ページに大量の読み込みが発生する為、ページネーションによって1ページの掲載数を10件までとする。
* 検索フォームからの検索方法（indexページ＆header）と、一覧表示からの選択方法の二つを用意する。

# ページネーションの導入
* `gem 'kaminari'`をgemfileに追記し、インストール。これによりページネーションの機能を実装できる
* controllerに以下記載することで、1ページ10件までにできる。（@itemsindexは一覧表示で利用）

```app/controllers/items_controller.rb 
  def index
    @items = Item.all.page(params[:page]).per(10).order(item_name: 'ASC')
    @itemsindex = Item.all.order(item_name: 'ASC')
    # ほか省略
  end
```

* 最後部に以下を記載することで、最後部にページ切替のボタンを設置できる
` <%= paginate @items %>`
* 好きなデザインのviewのbootstrapを選んで、以下実施
`rails g kaminari:views bootstrap4` 
* CSSで微調整（クラス名はviews/kaminariでわかる）

# 検索機能の実装
* ransack導入（Searchアクションは利用しない。indexページを再利用）。
* application.controllerに以下を追記する

```application.controller.rb
  def set_search
    @search = Item.ransack(params[:q])
    @search_items = @search.result
    @check = params[:q]
  end
```

* `<% if @search_index_items.blank? %>`を利用して、検索にヒットしない場合は「該当するxxxxxはありません」と表示させる。
* 検索フォームだけでなく、五十音順でitemを並べることでユーザーが一覧から選ぶことができる仕様のコードも併記。eachメソッドで` <% @itemsindex.each do |item| %>`とすればOK。五十音順は、controller側でASC定義。

```app/views/items/index.html
<%# 検索機能【検索から探す】＆【一覧から探す】 %>
 <div class="main-search-box">
  <div class="box28">
  <span class="box-title">検索から探す<i class="fas fa-search"></i></span>
  <%= search_form_for @search_index, url: items_path do |f| %>
  <%= f.text_field :item_name_cont, style: "width:90%;height:auto;margin-bottom:20px;border-color:#5cb525;", class: "form-control me-2", placeholder: 'xxxxxを入力...'%>
  <button class="btn btn-outline-success" type="submit">Search</button>
  <% end %>
  <br>
 <%# 検索がitem_nameに該当しない場合は「該当ありません」を表示する %>
 <% if @search_index_items.blank? %>
  <div>該当するxxxxxはありません</div>
 <% end %>
 <% if @search_index.conditions.present? %>
  <% @search_index_items.each do |item| %>
  <a class="btn btn-radius-solid2" href= <%= item_path(item.id) %>><%= item.item_name %></a> 
  <% end %>
<% end %>  <br>

</div>

 <%# 五十音順はcontroller側で定義（ASC） %>
 <div class="box28a">
    <span class="box-title">一覧から探す(五十音順)<i class="fas fa-search"></i></span>
   <% @itemsindex.each do |item| %>
   <a class="btn btn-radius-solid2" href= <%= item_path(item.id) %>><%= item.item_name %></a>  
  <% end %>
 <br>

</div>
</div>

 <%# ページネーションで10個リミット %>
 <%= paginate @items %>

```

# ヘッダーに検索フォームを設ける方法
* 以下をheaderのhtmlに記載する

```app/views/items/_header.html
   <%# ヘッダーから一発で検索結果が出るように実装 %>
  <%= search_form_for @search, url: items_path do |f| %>
  <%= f.text_field :item_name_cont, class: "form-control me-2", placeholder: 'xxxxxを入力...'%>
  <button class="btn btn-outline-success" type="submit">Search</button>
  <% end %>
 <% if @search_items.blank? %>
 <i class="fas fa-arrow-alt-circle-right fa-2x"></i>
  <div>該当するxxxxxはありません</div>
 <% end %>
 <% if @search.conditions.present? %>
  <% @search_items.each do |item| %>
  <i class="fas fa-arrow-alt-circle-right fa-2x searcharrow"></i>
  <a class="btn btn-radius-solid2" href= <%= item_path(item.id) %>><%= item.item_name %></a> 
  <% end %>
<% end %>  <br>
 </form>
```