search
LoginSignup
39
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

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

実現したいこと

1つのモデルに関連(ネスト)するモデルのカラムまで、検索対象にしたい

具体的には、古着屋の店舗名だけでなく、エリア名(1対多)や取り扱いブランド名(多対多)まで含めて一括検索したい。

スクリーンショット 2020-07-11 17.45.47.png

結論

フォームタグの要素名に、関連するモデル名_関連するモデルのカラム名を指定する

関連するモデルが、対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を利用した色々な検索フォーム作成方法まとめなどの記事を参考にしてください。

モデル間のアソシエーション

※関連する箇所のみ記載

スクリーンショット 2020-07-11 18.17.14.png

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
39
Help us understand the problem. What are the problem?