LoginSignup
19
19

More than 3 years have passed since last update.

【Rails】ransackで検索機能を実装する(ヘッダーにも検索窓を設置するときの対応)

Posted at

はじめに

gemのransackを使用して検索機能を実装する方法を簡単にまとめました。
またヘッダーにも検索窓を設置したときのポイントについても記載しました。
実装方法にアドバイス等ありましたら是非コメントをお願いします。

バージョン

・Ruby 2.7.0
・Rails 6.0.2.1

基本的な検索機能の実装

今回検索の対象とするのは、ユーザー(usersテーブル)一覧と、その投稿である本(booksテーブル)一覧とします。
それぞれの一覧画面(indexビュー)に検索窓を設けます。

gemのインストール

ransackをgemファイルに記載。

Gemfile(抜粋)
gem 'ransack'

bundle installでインストール。

ビュー

それぞれのindexビューに検索窓を実装します。

users/index.html.slim(抜粋)
= search_form_for @q do |f|
  = f.search_field :name_cont, placeholder: "ユーザー名で検索"
  = f.submit "検索"
books/index.html.slim(抜粋)
= search_form_for @q do |f|
  = f.search_field :title_cont, placeholder: "本の題名で検索"
  = f.submit "検索"

*_cont*に検索対象となるカラム名(ユーザーのnameと本のtitle)を記入することにより、
検索ワードを含む(contains)データを取得するための処理となります。

*_cont以外にも様々な検索オプションがあり、例えば完全一致としたい場合は*_eqを使用します。
ransackのgithubに色々のっております。

コントローラー

users_controller.rb(抜粋)
def index
    @q = User.ransack(params[:q])
    @users = @q.result(distinct: true)
end
books_controller.rb(抜粋)
def index
    @q = Book.ransack(params[:q])
    @books = @q.result(distinct: true)
end

検索ワードをparams[:q]で受け取り、検索で該当したデータをそれぞれ@users@booksに入れ、
再びindexビューに返す形です。

以上で簡単な検索機能の実装は完了です。

ヘッダーにも検索窓を設置する

ヘッダーの方にも検索窓を「追加で」実装する場合は工夫が必要となります。
今回はヘッダーの検索窓で本(booksテーブル)を検索できるようにします。

ヘッダーのビューファイルに下記記載。

header.html.slim(抜粋)
= search_form_for @q_header, url: books_path do |f|
  = f.search_field :title_cont, placeholder: "本の題名"
  = f.submit "本を検索"

全画面に適応させるためapplication_controller.rbに下記記載。

application_controller.rb(抜粋)
before_action :set_q_for_book

def set_q_for_book
  @q_header = Book.ransack(params[:q])
end

booksコントローラーの方には下記のとおり追記。

books_controller.rb(抜粋)
def index
    @q = Book.ransack(params[:q])
    @books = @q.result(distinct: true)
    if @q_header
      @books = @q_header.result(distinct: true)
    end
end

ポイント① @q_header

indexビューで使用した@qとは別に@q_header(名前は任意)を用います。
ヘッダーの方でも@qとしてしまうと、本のindexビューは問題なく表示されますが、
ユーザーのindexビューで下記のエラーが生じます。

undefined method `title_cont' for Ransack::Search<class: User, base: Grouping <combinator: and>>:Ransack::Search

Userクラスの検索に関してtitle_contメソッドが定義されていない、ということですね。

ユーザーのindexビューに遷移する前にusersコントローラーにて

@q = User.ransack(params[:q])

と定義しているため、@qのクラスがUserクラスに上書きされてしまうためです。

ポイント② フォームにパスを記載

どの画面からヘッダーで検索しても本のindexビューにとぶように、
url: books_pathとパスを明記する必要があります。

まとめ

ヘッダーでの検索窓の設置について詰まってしまったので今回記事にしました。
参考になりましたら幸いです。

19
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19