gemのransack
を用いずに複数条件での検索を実装しました。
リレーションのできている異なる2つのテーブルのカラムを用いて検索出来るようにします。
#viewで検索窓を実装
areaテーブルのarea_name(地域)とshopテーブルのname(お店の名前)の組み合わせで検索できるよう実装する。
#フォームで:search_area, :search_shopを受け取れるようにする。
#shops_pathへ送り、 shops/indexページで検索結果を表示させた
<%= form_tag(shops_path, :method => "get") do %>
<%= text_field_tag :search_area,"",placeholder: "地域" %>
<%= text_field_tag :search_shop,"",placeholder: "お店の名前" %>
<%= submit_tag "検索", :name => nil %>
<% end %>
#フォームで入力された情報をコントローラで受け取る
search
というメソッドにフォームで入力された:search_area
と:search_shop
の2つの引数を渡す。
def index
@shops = Shop.search(params[:search_area],params[:search_shop])
end
現段階ではこのsearch
というメソッドが定義されていない。
その為、このsearch
メソッドをshopモデル
で定義する必要がある。
#検索するためのsearch
メソッドをモデルに定義する
#引数にsearch_area と search_shopの2つを取るsearchメソッドを定義
def self.search(search_area,search_shop)
#お店の名前の検索ではLIKE句を用いてお店の名前を部分一致で判断する
search_area_name= Area.find_by(area_name: search_area)
search_shop_name= Shop.where("shops.name LIKE ?", "%#{search_shop}%")
#どちらも空白か無効な文字列の場合は全ての店舗情報を返す
if search_area_name.blank? and search_shop_name.blank?
Shop.all
elsif search_area_name.blank?
search_shop_name
elsif search_shop_name.blank?
#引数として受け取ったsearch_areaの地域名を地域idに変換する
search_area_id = search_area_name.id
Shop.where(area_id: search_area_id)
else
search_area_id = search_area_name.id
#shopテーブルのarea_idとnameが一致する店舗の一覧を取得する
Shop.where(area_id: search_area_id).where("shops.name LIKE ?", "%#{search_shop}%")
end
end
LIKE ?
って何?→ https://qiita.com/seri1234/items/765423c2c46ca4114da0
これで先ほどコントローラに記述していたsearch
メソッドが使えるようになりました。
#おわり
joins
メソッドとかを使えばもっとsearch
メソッドを綺麗にできそうです。
何でもかんでもgemに頼りたくないなと考えつつ、いろいろ調べたもののどうにも上手くいかずsearch
メソッドの中身がかなり力技になった気がします。
2つの要素であれば条件分岐させることで実装できますが、要素が3つ以上になるとこのままでは分岐が大変なことになるのでその場合はransack
なり別の方法を使った方が良さそうです。