はじめに
・シンプルな検索機能を実装したんですが、商品名だけでなく説明文も検索条件に含めたいなーと思いました。
・LIKE句であいまい検索もしています。
・色々な方法があると思いますが、僕が実装した方法を書きます。
・間違いなどあればご指摘いただけますと幸いです。
検索窓で検索します

キーワードを入力して、検索ボタンをクリック。
検索結果画面に遷移して、検索結果が表示される。
といった感じです。
こんなふうに実装しました
# 検索窓
.container
= form_with(url: search_items_path, local: true, method: :get, class: "hoge") do |f|
= f.text_field :key, placeholder: "キーワードから探す", class: "fuga", id: "hogehoge"
%button{type: "submit", class:"fugafuga"}
name="key"になっているところ(:key)がポイントです。
# itemsにネストすることと、collectionを使ってsearchアクションへのルーティングを設定します
resources :items, only: [:index, :show, :new] do
collection do
get 'search'
end
end
collectionはルーティングに:idがつかない、memberは:idがつくという違いがあります。
今回は検索結果を一覧表示する都合上、idは関係ないのでcollectionを使います。
# searchメソッドを追加します
def search
@search_items = Item.search(params[:key])
end
class Item < ApplicationRecord
def self.search(search)
if search != ""
Item.where(['name LIKE(?) or explanation LIKE(?)', "%#{search}%", "%#{search}%"])
else
Item.all
end
end
end
モデルファイルのポイントは以下のとおりです。
・クラスメソッドだからselfを使っています。Item.searchの意味です。
・if文は検索フォームに何か値が入っていた場合、以下のように検索しますよという意味です。
・検索はnameカラムをLIKE句を使ってあいまい検索をしますよ、もしくは、explanationカラムをLIKE句を使ってあいまい検索をしますよ、という意味です。
・"%#{search}%", "%#{search}%"は両方とも必要です。nameカラムとexplanationカラムの分ですね。片方でも欠けているとエラーが発生します。
・else以降は検索フォームに何も値が入っていなければ、商品を全て取り出しますよという意味です。
.PickupContainer
%h2.PickupContainer__title
検索結果
%ul.PickupContainer__items
- @search_items.each do |item|
%li.PickupContainer__items--item
= link_to "/items/#{item.id}" do
.DetailBox
.DetailBox__name
= item.name
.DetailBox__details
%ul
%li
%span ¥
= item.price.to_s(:delimited)
%p
(税込)
検索結果はこんな感じです
Gyazoを貼っておきます。
eachメソッドで検索結果が一覧で出てくるようにしています。
https://gyazo.com/3ae03fd0fabed3dc615ae47ad4f166e3
まとめ
複数カラムを検索条件に含めるための、モデルファイルでの記述が今回のキーポイントです。
が、ルーティングやコントローラーの記述にも大事な部分があるので注意です。
ありがとうございました。