実現したいこと
1つのモデルに関連(ネスト)するモデルのカラムまで、検索対象にしたい
具体的には、古着屋の店舗名だけでなく、エリア名(1対多)や取り扱いブランド名(多対多)まで含めて一括検索したい。
結論
フォームタグの要素名に、関連するモデル名_関連するモデルのカラム名
を指定する
関連するモデルが、対1
(belongs_to: hoge、やhas_one: fuga)
例えば、shopモデルに紐づくareaモデルのエリア名(name)を検索条件にしたい時
= f.フォームヘルパー :要素名
の要素名
をarea_name_cont
とする。
分解すると
area → 関連するモデル名
name → 関連するモデルのカラム名
cont → 部分一致を指定する述語
となります。
= search_form_for(@q, url: shop_search_path) do |f|
= f.text_field :area_name_cont
# shopモデルに紐づくareaモデルの、エリア名(name)
関連するモデルが、対多
(has_many: hogesなど)
例えば、shopモデルに紐づくbrandsモデルのブランド名(name)を検索条件にしたい時
= f.フォームヘルパー :要素名
の要素名
をbrands_name_cont
とする。
分解すると
brands → 関連するモデル名 ※shop has_many: brandsなので複数形
name → 関連するモデルのカラム名
cont → 部分一致を指定する述語
となります。
= search_form_for(@q, url: shop_search_path) do |f|
= f.text_field :brands_name_or_genres_name_cont
# shopモデルに紐づくbrandモデルの、ブランド名(name)
# shopモデルに紐づくgenreモデルの、ジャンル名(name)
# ※紐づくモデルが複数の時は、モデル名が複数形になることに注意
ちなみに、_or_
などでカラム名を繋ぐと、複数カラムを検索対象にできます。
実際のransackの使い方などについては、[Rails]ransackを利用した色々な検索フォーム作成方法まとめなどの記事を参考にしてください。
モデル間のアソシエーション
※関連する箇所のみ記載
# shopモデル
belongs_to :area, optional: true
has_many :shop_genres
has_many :shop_brands
has_many :genres, through: :shop_genres
has_many :brands, through: :shop_brands
# areaモデル
has_many :shops
# brandモデル
has_many :shop_brands
has_many :shops, through: :shop_brands
# shop_brandモデル
belongs_to :shop
belongs_to :brand
# shop_genreモデル
belongs_to :shop
belongs_to :genre
関連を調べる方法
ransackable_associations
というメソッドを使うと便利です。
1. アプリケーションディレクトリでrails c
# 該当のアプリケーションディレクトリで実行
$ rails c
Running via Spring preloader in process 61541
Loading development environment (Rails 5.0.7.2)
[1] pry(main)>
2. モデル名.ransackable_associations
を実行
# 今回はShopモデルとの関連を調べたいので、Shop.ransackable_associationsとすると
Shopモデルに紐づくモデルが表示される
[1] pry(main)> Shop.ransackable_associations
=> ["user", "area", "shop_genres", "shop_brands", "genres", "brands"]
[2] pry(main)>
参考
Ransackで簡単に検索フォームを作る73のレシピ -026 関連
Ransackで親テーブルや子テーブルのカラムで複数検索する方法