自分が複数ワードでの検索機能を実装する際に結構調べたので備忘録として。
目標
複数ワードかつ複数カラムを跨いだ検索を可能にする。
開発環境
Ruby2.6.3
Rails5.2.5
実装方法
ルーティングを記述
get '/search' => 'searches#search'
検索ボタンを押したら、srarchesコントローラーのsearchアクションが実行されます。
検索フォーム(部分テンプレートにしています)
<%= form_with url: search_path, method: :get, local: true do |f| %>
<%= f.text_field :keyword %>
<%= f.submit "検索" %>
<% end %>
検索フォームに入れた内容をkeywordとしてコントローラーへ送ります。
controller
def search
@keywords = params[:keyword]
@posts = Post.all
split_keywords = @keywords.split(/[[:blank]]+/)
split_keywords.each do |word|
@posts = @posts.where(['カラム名 LIKE ? OR カラム名 LIKE ?・・・', ・・・"%#{word}%", "%#{word}%"])
end
end
簡単に解説していきます。
@keywords = params[:keyword]
→検索フォームから入力されたkeywordを取得。
@posts = Post.all
→@postsオブジェクトを作成。
kaminari使用時は@posts = Post.page(params[:page]).per(5)のように記述。
split_keywords = @keywords.split(/[[:blank]]+/)
→検索ワードを分割しています(splitメソッドは文字列を分割して配列として格納します)
.split(/[[:blank]]+/)の記述で半角、全角の空白どちらを入力しても分割してくれます。
split_keywords.each do |word|
→入力したキーワードを検索にかけていきます。
@posts = @posts.where(['カラム名 LIKE ? OR カラム名 LIKE ?・・・', ・・・"%#{word}%", "%#{word}%"])
→検索をかけたいカラムを記述していきます。カラムの数だけ"%#{word}%"の記述が必要になります。
"%#{word}%"で部分一致の検索になります。
最後に検索結果のview
<%= @keywords %>の検索結果
<% if @posts.empty? %>
該当する投稿はありません。
<% else %>
<%= @posts.each do |post| %>
・
・
<% end %>
<% end %>
# kaminari使用時のみ
<%= paginate @posts %>
empty?はRubyのメソッドです。
空文字、空配列、空ハッシュの場合にtrueを返してくれます。
なので今回検索したキーワードに該当する投稿がない場合に「該当する投稿がありません」と表示されるようにしました。
該当する投稿があった場合はeach文で取り出します。
以上です。
間違っているところやもっと効率の良い書き方があれば教えていただけると助かります。