Userクラスのmemoカラムをフリーワード検索(全文検索)するにはどうすれば良いかという話。
app/admin/user.rb
filter :memo_cont
としておくと部分一致検索が可能だが、hoge fuga
で検索すると "hoge fuga"
による部分一致検索となってしまう。
検索ワードをスペースで区切った単語で部分一致によるAND検索を行いたい。
つまり、検索ワードとして hoge fuga
が入力された時に次のSQLが発行されるようにしたい。
SELECT * FROM "users" WHERE "memo" ILIKE '%hoge%' AND "memo" ILIKE '%fuga%'
ranscker の作成
ActiveAdmin は ransack を利用しているので、まずは対象のモデルに ransacker を作ってあげる。
app/models/user.rb
scope :memo_freeword_all, -> (search) {
User.search(memo_cont_all: search.split(/ | /)).result
}
def self.ransackable_scopes(auth_object = nil)
%i(memo_freeword_all)
end
これで次のように利用できる。
User.search(memo_freeword_all: 'hoge fuga').result
#=> 上記のSQLが発行される
filter の指定
あとは memo_freeword_all
を filter で指定してあげればよい。
app/admin/user.rb
filter :memo_freeword_all, as: :string
ラベルのI18n対応
ちなみに辞書ファイルに次のように定義しておけばラベルとして利用される。
config/locales/ja.yml
ja:
activerecord:
attributes:
user:
memo_freeword_all: 'メモ(いずれかの語を含む)'
その他、検索条件の書き方
app/admin/user.rb
# '含まれる', '等しい', 'で始まる', 'で終わる' を選べる
filter :memo
# 完全一致検索
filter :memo_eq
# 部分一致
filter :memo_cont
# 前方一致
filter :memo_starts_with
# 後方一致
filter :memo_ends_with