[Rails]ransackで関連するモデル(親や子)のカラムをまたいで検索する方法


実現したいこと

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.rb
# 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.rb
# areaモデル
  has_many :shops
brand.rb
# brandモデル
  has_many :shop_brands
  has_many :shops, through: :shop_brands
shop_brand.rb
# shop_brandモデル
  belongs_to :shop
  belongs_to :brand
shop_genre.rb
# shop_genreモデル
  belongs_to :shop
  belongs_to :genre

関連を調べる方法

ransackable_associationsというメソッドを使うと便利です。

1. アプリケーションディレクトリでrails c

terminal
# 該当のアプリケーションディレクトリで実行

$ rails c
Running via Spring preloader in process 61541
Loading development environment (Rails 5.0.7.2)
[1] pry(main)> 

2. モデル名.ransackable_associationsを実行

terminal
# 今回は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で親テーブルや子テーブルのカラムで複数検索する方法