ぱーりー on rails

たまごにひびすらわれてない

ransackで検索機能実装

まずransackというgemをgemfileに

gem 'ransack'

と追加して、$ bundle install
します。



検索機能のだいたいのイメージとしては
検索フォームがあって、
そこに検索ワードを入力したり、セレクトボタンで検索条件を選択して、
「検索ボタン」をおしたら「検索結果画面」が開かれて検索結果が表示されるというイメージですよね。
ということはまずはviewファイルから作って行きましょう。
まずは検索ワードなどを入力する検索フォームの実装をしていきます。

ここで利用するのが「部分テンプレート」です。

viewファイルのhtml.erbファイル名の先頭に「_」をつけることで部分テンプレートを作成することができます。
そのためコードを短くスッキリさせることができます。

今回の場合だと検索フォームだけの部分テンプレートをつくることで、
検索フォームがどんなコードであるかを一目で見ることができ、検索フォームを追加したい画面には
<%= render 'search_form', f: f %>
を追加するだけで検索フォームを呼び出せます。




検索機能をつけたいhtml.erbファイルに以下を追加。
私の場合はindex.html.erbでした。

<%= search_form_for(@q, url: users_search_path, html: { method: :get, class: 'form-inline', role: 'form' }) do |f| %>
  <%= render 'search_form', f: f %>
<% end %>

@qはあとから説明します。
url: admin_users_search_pathの部分で検索結果画面を呼び出します。
url: というオプションでフォームの送信先のパスを指定することができます。


  • その検索結果画面をsearch.heml.erbを作成します。
<h1 class='page-header'>ユーザー検索結果</h1>
<div class='row'>
  <div class='col-md-12'>
    <div class='panel panel-inverse' data-sortable-id='table-basic-2'>
      <div class='panel-body'>

        <table class='table table-hover'>
          <thead>
          <tr>
            <th>ユーザー名</th>
            <th>email</th>
            <th>県名</th>
            <th style='width: 200px;'></th>
          </tr>
          </thead>
          <tbody>
            <% @users.each do |user| %>
              <tr>
                <td><%= user.name %></td>
                <td><%= user.email %></td>
                <td><%= user.prefecture_name %></td>
                <td>
                    <%= link_to '詳細', admin_user_path(user), class: 'btn btn-default' %>
                    <%= link_to '編集', edit_admin_user_path(user), class: 'btn btn-primary' %>
                    <%= link_to '削除', admin_user_path(user), method: :delete,
                    data: { confirm: 'こちらのプロジェクトを削除しますか?' }, class: 'btn btn-danger' %>
                </td>
              </tr>
            <% end %>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>

部分テンプレートとして_search.form.html.erbファイルの作成します。

<div class='panel panel-inverse'>
  <div class='panel-body'>
    <%= f.text_field :name_cont, placeholder: 'ユーザー名', class: 'form-control' %>
    <%= f.text_field :email_cont, placeholder: 'メールアドレス', class: 'form-control' %>
    <%= submit_tag '検索', class: 'btn btn-info w40 mr10' %>
    </div>
</div>

続いてルーティングの設定をします。

 get  'users/search'              =>   'users#search'

これで検索ボタンをおすと検索結果のページに移動することができます。


続いて検索機能をつけたいcontrollerを作成します。

  def index
    @users = User.all
    @q = User.search
  end

  def search
    @q = User.search(search_params)
    @users = @q
                .result
                .order(:created_at)
  end

private
  def search_params
    params.require(:q).permit(:name_cont, :email_cont)
  end


1行ずつプログラムを読んでいくと、
まずはindexアクションの部分。
@usersでUserモデルの情報をとってきて表示させることができます。(@users = User.all)
Userモデルからsearchしたものを@qという変数に代入します。(@q = User.search)

(※なんで@qなのかは調べてみたのですがわかりません。ransackでは@qと変数にするみたいです。。。)



次に、searchアクションの部分は一旦飛ばして
ストロングパラメーターの説明をします。
search_paramsを定義し、params.require(:q).permit(:name_cont, :email_cont)で

name_cont,(名前のlike検索)
email_cont(emailのlike検索)を通すことができます。

で、serchアクションでは
そのストロングパラメーター search_paramsを引数として@qで検索した結果を@usersに代入して
.resultで検索結果を表示し、.orderで作成時間ごと(:created_at)検索結果を
search.html.erbで@userをeachメソッドによりをけっかんを表示させています。




これで完成です。


また、検索フォームは f.collection_select などでセレクトボタンをつかってつくることもできます!

    <%= f.collection_select :user_id_eq, User.all, :id, :name, { include_blank: 'ユーザーを選択してください' }, { class: 'form-control search-form' } %>

こんなかんじでできます!