Ryota400’s blog

エンジニアを目指して書いてます。

掲示板の検索機能を実装

ransackで検索機能を実装する

ransackとは、簡単に検索フォームを作成できるgem

Gemfile

gem 'ransack'
bundle install

コントローラーの修正

今回検索フォームを配置する、掲示板一覧(index)とお気に入り一覧(bookmarks)部分を修正していく。

app/controllers/boards_controller.rb

class BoardsController < ApplicationController
  def index
    @q = Board.ransack(params[:q])
    @boards = @q.result(distinct: true).includes(:user).page(params[:page])
  end

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

params[:q]でフォームで検索入力した文字列を取ってくる。

@q.resultで検索結果を渡している。 distinct: trueオプションを使えば、結果の重複を防ぐことができる。

includes 何度もSQLを発行するN+1問題が起こらないように、関連するデータも含めて取得している。

View

それぞれのアクションでは異なるViewファイルを表示しますが、「検索フォーム」は共通

app/views/boards/_search_form.html.erb

<%= 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 %>

ansackのsearch_form_forヘルパーを使用します。

第一引数に、先程定義した検索オブジェクトqを渡します。

urlオプションを設定し、リクエストするUrlを指定する。

今回は指定対象がbookmarks_boards_pathだけだったので、検索フォームからrenderするときにurlを渡しているが、 同じ検索フォームを使い回しし、ページによって検索対象が変わるときには、url: request.path_infoと渡す。

パーシャルファイルの_search_form.html.erbをrenderする各所で、ローカル変数に値を渡す。 app/views/boards/index.html.erb

<%= render 'search_form', q: @q, url: boards_path %>

app/views/boards/bookmarks.html.erb

<%= render 'search_form', q: @q, url: bookmarks_boards_path %>

参考文献

qiita.com