gem ransackを使用し検索機能の実装

実装内容

gem 'ransack'を使用し、掲示板一覧画面とブックマーク一覧画面に以下のようなフォームを設置する。

  • 入力された文言が「掲示板のtitle,body」に含まれている掲示板のみを表示させる。
  • ブックマーク一覧のページで検索した場合は「ブックマークした掲示板の中から」検索条件に合致したものを表示させる。

  • 掲示板一覧画面での検索はboards#indexアクション、

  • ブックマーク一覧画面での検索はboards#bookmarksアクションで行う。

導入

gem 'ransack'
  

bundle install

controller

掲示板一覧(index)アクションとブックマーク一覧(bookmarks)アクションを修正

~
    def index
    if logged_in?
      @q = Board.ransack(params[:q])
      @boards = @q.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page])
    else
      redirect_to login_path, danger: 'ログインしてください'
    end
  end

    def bookmarks
      @q = current_user.bookmark_boards.ransack(params[:q])
      @bookmark_boards = @q.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page])
    end
~

params[:q]で検索フォームに入力した文字を取得(viewから送られてきたパラメータ)デフォルトで:qとなっている。→インスタンス変数@qを定義。
ransackメソッド、送られてきたパラメータをもとにテーブルからデータを検索。
resultメソッドでransackメソッドで取得したデータをActiveRecord_Relationのオブジェクトに変換し、検索結果を渡す。
(distinct: true)で重複を防ぐ

includesメソッドでN+1問題の回避。
orderメソッドで並び替え。
pageメソッドでページネーションの実装。

view

検索フォームのパーシャルを作成

  <%= search_form_for q, url: url do |f| %>
  <div class='input-group mb-3'>
    <%= f.search_field :title_or_body_cont,
                        class: 'form-control',
                        placeholder: '検索ワード' %>
    <div class="input-group-append">                   
     <%= f.submit '検索', class: 'btn btn-primary' %>
    </div>
  </div>
<% end %>

search_form_forメソッドはransackで用意されているメソッド
form_withやform_forと同じ
検索オブジェクトqを指定。
urlオプションでリクエストするurlを渡す。→renderでパーシャルを読み込む時に指定。

f.search_fieldで入力フォームを作成すると検索フォームとして作成される。
今までは文字の場合→f.text_fieldで記述していた。
f.search_fieldを指定することで、inputタグにtype="search"が記述され、フォームの右に「x」ボタンが表示されるようになる。
:title_or_body_contで検索対象のカラムを指定。今回は2つあるのでorで区切る。

パーシャルを読み込む

掲示板一覧画面とブックマーク一覧画面にパーシャルをレンダーさせる。
ローカル変数qに値を渡す。
pathは各アクションのやつを指定。

<!-- 検索フォーム -->
<form>
  <%= render 'boards/search_form', url: boards_path, q: @q %>
</form>
<!-- 検索フォーム --><form>
  <%= render 'boards/search_form', url: bookmarks_boards_path, q: @q %>
</form>