#はじめに
全国津々浦々の Ransacker の皆様、今日も元気に Ransack 使ってますか?
Ransack は DB に対する検索を実装する上ではお手軽に使えるので利用されてる方も多いと思います。
ただ、Ransack を使ってて全文検索までとはいかずとも「もうちょっと込み入った検索もしたいな・・・」って思った時に痒いところに手が届かずに悶絶していませんか?
ここでは、そんな時に便利な ActiveRecord の Scope を利用した検索の実現方法を紹介します。
#Ransack における検索
Ransack では基本的に2種類の検索方法が準備されています。
一つは「Simple Mode」で、もう一つは「Advanced Mode」です。
Simple Mode
Simple Mode では、Predicates
と呼ばれる検索用の述語を指定することで簡易な検索を行います。
例えば users
テーブルの name
カラムに指定した文字が含まれている事、といった検索をしたい場合は User.search(name_cont: 'ruzia').result
といった形になります。
条件は or
や and
などで連結することも可能なので、簡単な検索であれば十分使えます。
Predicates
の詳しい書き方は以下のURLを参照して下さい。
https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
Advanced Mode
Advanced Mode では、Condition Groups
と呼ばれる検索条件のグループを複数組み合わせる事で複雑な検索を行います。
Condition Groups
はネストする事もでき、相当複雑なクエリの組み立てが行えます。
とは言え言葉だけではイメージが湧かないと思うので、詳しくは以下の URL を参照して下さい。
http://ransack-demo.herokuapp.com/users/advanced_search
触ってみればわかると思いますが、相当複雑な条件を指定できます。
#帯に短し襷に長し
というわけで Ransack には 2 つの検索方法があるわけですが、絶妙に痒いところに届かないっ・・・!
実際にいろいろ作ろうとすると Simple Mode よりもちょっと複雑な条件を指定したいけど、Advanced Mode ほど自由度が高く無くても良い、という状況によく陥ります。
そして大体脳裏に浮かぶのは「Scope なら簡単に書けるのに・・・!」という台詞ではないでしょーか。
Simple Mode だとやりたい事が実現できないけど、かといって Advanced Mode を使って Condition Groups
を組み立てるのはめんどくさい気が進まない・・・
そんなあなたに、ransackable_scopes!!
#ransackable_scopes を利用した検索
Ransack には ransackable_scopes という機能があります。
ransackable_scopes を一言で表現すると、「Scope を利用した Simple Mode による検索」です。
例えば、name
と address
を持っている User
がある際に「ruzia 東京」とかいった感じのフリーワード検索っぽいものをしたいとします。
その場合、例えば以下の様な形で実現できてしまいます。
class User < ActiveRecord::Base
# あくまでも例なので、DBの負荷とか考慮してないです
scope :by_freeword, -> (freeword) {
user_table = User.arel_table
freeword_node = Arel::Nodes::InfixOperation.new('||', user_table[:name], user_table[:address]))
result = all
freeword.split(/ | /).each do |term|
result = result.where(freeword_node.matches(term))
end
result
}
def self.ransackable_scopes(auth_object = nil)
%i[by_freeword]
end
end
Model
を上記の様な形で実装しておくと
User.search(by_freeword: 'ruzia 東京').result
という実装が可能になります。
つまり、Simple Mode における Predicates
として Scope が利用できちゃうわけですね、すてき!
#まとめ
というわけで、実は Ransack って Scope を使った検索もできちゃうんだよ!という紹介でした。
実はこの機能、Ransack の前身である MetaSearch には結構前からあったんですよね。
なかなか Ransack に実装されなくて悶々としてたのですが、ちょっと前に以下の pull request でやっと取り込まれました!
Ransack の sort_link
などの便利な機能を使いつつも Scope を利用した複雑な検索も実現できるため、全文検索ほどではない場合にとても便利だと思います。
まだ使った事が無い方は、ぜひお試しを!
参考情報
ransackable_scopes:https://github.com/activerecord-hackery/ransack#using-scopesclass-methods
ActiveRecordのScope:http://guides.rubyonrails.org/active_record_querying.html#scopes