ActiveAdmin のフィルターでAND検索する
ActiveAdmin の filter では Ransack を利用することができる。
例えば以下のように定義してあげると、 nameカラムに対して LIKE検索することができる。
ActiveAdmin.register User do fitler :name_matches end
Ransackでは cont_allを利用することで、特定のカラムを複数の単語でAND検索することができる。
では、ActiveAdminでフォームにスペース区切りで複数の単語を入力した場合にnameカラムをAND検索したい場合はどうすれば良いだろうか
ActiveAdmin.register User do fitler :name_cont_all end
これまでの説明であれば、なんとなく上記のようなfilterを定義してあげるとできそうな気がする。 しかし上記のfilter を定義しフォームに「hoge fuga」を入力し検索を行うと以下のようなクエリが発行された。
SELECT COUNT(*) FROM (SELECT 1 AS one FROM `users` WHERE `users`.`deleted_at` IS NULL AND (`users`.`name` LIKE '%hoge fuga%') LIMIT 30 OFFSET 0) subquery_for_count
「hoge fuga」を1つの単語としてLIKE検索しているのである。 これは Ransack側は単語を配列で渡されることを期待しているがActiveAdminは素直に文字列で渡しているためである。
AND検索するためにはフォームに入力した文字列が、Rnsackに渡る前に配列に変換すれば良い。
例えば、以下のように before_action で文字列を配列に変換するなどが考えられる。
ActiveAdmin.register User do fitler :name_cont_all controller do before_action :adjust_search_params, only: :index private def adjust_search_params return if params[:q].nil? || params[:q][:name_cont_all].nil? params[:q][:name_cont_all] = params[:q][:name_cont_all].split(/[[:blank:]]+/) end end end
ちなみにActiveAdmin側でスペース区切りで入力された単語を配列に分割するようにPull Requestが投げられているようだががマージには至っていない。