#はじめに
gemのransack
を使用して検索機能を実装する方法を簡単にまとめました。
またヘッダーにも検索窓を設置したときのポイントについても記載しました。
実装方法にアドバイス等ありましたら是非コメントをお願いします。
#バージョン
・Ruby 2.7.0
・Rails 6.0.2.1
#基本的な検索機能の実装
今回検索の対象とするのは、ユーザー(usersテーブル)一覧と、その投稿である本(booksテーブル)一覧とします。
それぞれの一覧画面(index
ビュー)に検索窓を設けます。
###gemのインストール
ransack
をgemファイルに記載。
gem 'ransack'
bundle install
でインストール。
###ビュー
それぞれのindex
ビューに検索窓を実装します。
= search_form_for @q do |f|
= f.search_field :name_cont, placeholder: "ユーザー名で検索"
= f.submit "検索"
= search_form_for @q do |f|
= f.search_field :title_cont, placeholder: "本の題名で検索"
= f.submit "検索"
*_cont
の*
に検索対象となるカラム名(ユーザーのname
と本のtitle
)を記入することにより、
検索ワードを含む(contains)データを取得するための処理となります。
*_cont
以外にも様々な検索オプションがあり、例えば完全一致としたい場合は*_eq
を使用します。
ransackのgithubに色々のっております。
###コントローラー
def index
@q = User.ransack(params[:q])
@users = @q.result(distinct: true)
end
def index
@q = Book.ransack(params[:q])
@books = @q.result(distinct: true)
end
検索ワードをparams[:q]
で受け取り、検索で該当したデータをそれぞれ@users
と@books
に入れ、
再びindex
ビューに返す形です。
以上で簡単な検索機能の実装は完了です。
#ヘッダーにも検索窓を設置する
ヘッダーの方にも検索窓を「追加で」実装する場合は工夫が必要となります。
今回はヘッダーの検索窓で本(booksテーブル)を検索できるようにします。
ヘッダーのビューファイルに下記記載。
= search_form_for @q_header, url: books_path do |f|
= f.search_field :title_cont, placeholder: "本の題名"
= f.submit "本を検索"
全画面に適応させるためapplication_controller.rb
に下記記載。
before_action :set_q_for_book
def set_q_for_book
@q_header = Book.ransack(params[:q])
end
books
コントローラーの方には下記のとおり追記。
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
とパスを明記する必要があります。
#まとめ
ヘッダーでの検索窓の設置について詰まってしまったので今回記事にしました。
参考になりましたら幸いです。