はじめに
Rails初学者です。
以下の記事を参考にさせていただきAND検索を実装したので、メモ
追加情報として、AND検索を実装したときにある不具合が起こったので、そこについても記していきます。
やり方
ransackを用いたビューとコントローラーの実装は以下のようになっています。
<%= search_form_for @search , url: posts_path do |f| %>
<%= f.search_field :title_or_body_cont, placeholder: "キーワードで質問を探す" %>
<%= f.submit%>
<% end %>
class PostController
def index
@search = Question.ransack(params[:q])
@posts = search.result
end
end
これに対して、複数のワード用いてAND検索を行いたい場合は、以下のようにパラメータを渡す
def index
keyword = params[:q][:title_or_body_cont].split(' ') # 'hoge hige'
@posts = Post.ransack({ combinator: 'and', groupings: { 'a' => {title_or_body_cont: keyword[0]}, 'b' => {title_or_body_cont: keyword[1]}} })
end
上記の例では、Postモデルのtitleカラムとbodyカラムに対して'hoge'と'hige'の二つの文字列でAND検索を実行しています。
※groupings内の'a'や'b'の部分は、一意であれば何でも良い。
これらを踏まえた完全版が以下になります。
def index
key_words = params[:q][:title_or_body_cont].split(/[\p{blank}\s]+/) #'hoge hige'
grouping_hash = keywords.reduce({}){|hash, word| hash.merge(word => { title_or_body_cont: word })}
Post.ransack({ combinator: 'and', groupings: grouping_hash }).result
end
1行目、params[:q][:title_or_body_cont]には半角スペースあるいは全角スペースで区切られた形で、複数の検索ワードが入っています('hoge hige')。2行目は検索ワードを分割し、配列に格納している。3行目は、ransackに渡すgroupingsパラメータの中身を組み立てている。
ちなみにsplitの引数にある/[\p{blank}\s]+/
はよくある正規表現で半角スペースと全角スペースを認識します。
これで以下のようなハッシュが生成されます。
{
'hoge' => {title_or_body_cont: 'hoge'},
'hige' => {title_or_body_cont: 'hige'},
}
不具合の解消
これにて実装完了と思いきや以下のような不具合がおきました。
検索を実行すると。。。
検索フォームが空に。。。
しかしこの解決方法は簡単です。
viewをいじるだけです。
<%= search_form_for @search , url: posts_path do |f| %>
<%= f.search_field :title_or_body_cont, placeholder: "キーワードで質問を探す" ,value: params[:q][:title_or_body_cont] %>
<%= f.submit%>
<% end %>
f.search_field
にvalue
を追加してparams[:q][:title_or_body_cont]
を指定するだけ解消できます。