Railsでスペース区切りで複数キーワードにヒットする検索フォームを実装する方法


Ransackで検索機能を実装しようと思ったのですが、スペース区切りでヒットする検索が実装できませんでした。


・検索する文
「Railsでスペース区切りで複数キーワードにヒットする検索フォームを実装する方法」
・検索キーワード
[Rails]→ヒット [Rails スペース]→ヒットしない

空白区切りでもヒットする検索を実装してみました。
該当する文があれば、キーワードはいくつでも対応しています。
全角スペース、半角スペースどちらでも対応しています。


・検索する文
「Railsでスペース区切りで複数キーワードにヒットする検索フォームを実装する方法」
・検索キーワード
[Rails]→ヒット [Rails スペース]→ヒット [Rails スペース ヒット]

view

form_tagでindexのパスを指定しています。methodは検索なのでgetで指定。
searchアクションに飛ぶように指定します。
prams[:search]でフォームに「検索キーワード」と入力すると:3000/memos?utf8=✓&search=検索キーワード&commit=検索のようなURLが生成されます。

views/index.html.erb

<%= form_tag memos_path,:method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "検索" %>
<% end %>

controller

params[:search]が存在した場合と、しない場合でif文で表示の条件分岐をします。
今回はdeviseでログイン機能を実装していて、ログインしているユーザーのみの検索をしたいので、where(user_id: current_user.id)でログインしているユーザーのメモのみ表示します。

memos_controller.tb

def index
  @memos = Memo.where(user_id: current_user.id)

  if params[:search].present?
    @memos = @memos.search(params[:search]).where(user_id: current_user.id)
  else
    @memos = Memo.where(user_id: current_user.id)
  end
end

model

models/memos.rb

def self.search(search)
  if search
    patterns = search.split(/[ , ]/)
    sql_body = ''
    patterns.each do | pattern |
      sql_body += ' and ' unless sql_body.blank?
      sql_body += " body like '%#{pattern}%' "
    end
    sql = "select * from memos where #{sql_body} order by id desc"
    memo_ids = Memo.find_by_sql(sql)
    ids = []
    memo_ids.each do |qi|
      ids.push(qi.id)
    end
    where(:id => ids)
  else
    Memo.all
  end
end