ほろ酔い開発日誌

AI企業のエンジニアのブログです。機械学習、Web開発の技術的お話、ビジネスチックなお話、日常のお役立ち情報など雑多な内容でお送りします。

Rails サイト内検索機能を作った (AND検索にも対応)

サイトの記事数が増えてきてサイト内検索が欲しくなりました。というわけで検索機能を実装するためのgemのransackで検索機能を実装することにしました。

github.com

今回やろうと思っているのは記事のタイトル検索が出来ればいいなーと思っています。あと検索のときに空白で区切ってAND検索になるようにしたいと思います。

ひとまず、gemを入れます。

gem 'ransack'

それで、今回やりたいことを整理します。

  1. 全ページのヘッダーに検索窓をつける。
  2. /search?q=hoge みたいな感じでqueryを渡す。
  3. 検索ページに検索結果を表示する。

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

というわけで解消します。以下のサイトを参考にします。

www.mk-mode.com

まず、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検索とかあとひらがなでもカタカナでも取得してくれたりとか簡単に出来るので入れてみると便利だなとか思いました!