サイトの記事数が増えてきてサイト内検索が欲しくなりました。というわけで検索機能を実装するためのgemのransackで検索機能を実装することにしました。
今回やろうと思っているのは記事のタイトル検索が出来ればいいなーと思っています。あと検索のときに空白で区切ってAND検索になるようにしたいと思います。
ひとまず、gemを入れます。
gem 'ransack'
それで、今回やりたいことを整理します。
- 全ページのヘッダーに検索窓をつける。
/search?q=hoge
みたいな感じでqueryを渡す。- 検索ページに検索結果を表示する。
1. 全ページのヘッダーに検索窓をつける。
好きなように検索窓を作ってしまいます。「q」でvalueをgetメソッドで渡すのでその部分は注意してください。(qはqueryとか何でもいんですが)
= form_tag search_index_path, method: 'get' do = text_field_tag :q, '', placeholder: "気になるワードを入力" = button_tag type: 'submit' do %i.fa.fa-search
あと、classとかつけてstyle付ければいいですね。僕はfont-awesomeとか入れるの好きですが何でもいいですね。お好きに。
2. /search?q=hoge
みたいな感じでqueryを渡す。
それで、ひとつ注意があって単純にgetメソッドをつける以下みたいな余計なqueryがくっついてきてしまうことです。カッコ悪いですね。。
/search?q=hoge&utf8=✓&commit=submit
というわけで解消します。以下のサイトを参考にします。
まず、commitなんちゃらのほうを取り除きます。button_tagに name: nil のオプションを渡すだけです。うん、簡単。
= form_tag search_index_path, method: 'get' do = text_field_tag :q, '', placeholder: "気になるワードを入力" = button_tag type: 'submit', name: nil do %i.fa.fa-search
で次にconfig/initializer
に以下のファイルを作ればuft8なんちゃらが消えます。
module ActionView module Helpers module FormTagHelper def utf8_enforcer_tag "".html_safe end end end end
これでオーケー!
3. 検索ページに検索結果を表示する。
def index(q, page=1) @q = q query_arr = q.split(/[[:blank:]]+/) @search = Article.ransack(title_cont_all: query_arr) @articles = @search.result.published.newest.page(page) end
以下で詳しく解説します。
query_arr = q.split(/[[:blank:]]+/)
qは受け取ったqueryですが、空白で切り分けて配列にします。splitの引数に入れたやつで区切ってくれます。はじめ普通に /\s/
のようにすれば空白区切り出来るかと思ったのですが全角に対応出来ないみたいだったので探してみたらこんな感じでいけました。
Article.ransack(title_cont_all: query_arr)
Articleというテーブルに ransack
というメソッドをgemの力をかりて実行します。 title_cont_all
というオプションで値にqueryの配列を与えるとそれら全てを含む記事を引っ張ってくれます。
title_cont_all
の部分なのですが(検索するcolumn名)_cont_all
の意味で、今回はtitle
カラムを使いましたが適宜変更可能です。
それで後は好きに加工して表示させちゃってください! ( 上記サンプルコードは、action_argsとかkaminariといったgemを使ったことがコードに反映されてます。)
これで完成です!
正直まあこの程度の検索ならgem使わなくても...とか思ったりもしたのですが、and検索とかあとひらがなでもカタカナでも取得してくれたりとか簡単に出来るので入れてみると便利だなとか思いました!