Railsアプリケーションで検索機能を実装する場合、最近はRansackを導入するケースが増えているのではないかと思います。
(Perfect Ruby on Railsでも取り上げられてましたしね。)
Ransackには2つのモードがあります。
Simpleモードでは、controllerとviewのインタフェースとしてsearchオブジェクトを使って簡単に検索フォームの実装ができます。
searchオブジェクトは通常のRailsアプリケーションにおいてmodelのインスタンスでcontrollerとviewのやりとりしているのを置き換える形になります。view側にはform_for
に替わるsearch_form_for
というヘルパーメソッドが用意されています。
今回はもうひとつのAdvancedモードを試してみたいと思います。
確認環境
Rails 4.2.1 ransack 1.6.6
モデルのscopeを検索条件にする
- ransackを使って検索をする場合は、基本的にはモデルのもつカラム名に述語suffixを追加して検索条件を指定します。
- titleの完全一致
1
Post.ransack(title_eq: "It's a beautiful day")
- titleの部分一致
1
Post.ransack(title_cont: "It's a beautiful day")
- しかしモデルに定義定義済みのscopeを検索条件として使いたくなる場合があります。その場合には、クラスメソッド
ransackable_scopes
でransackの条件として利用するscopeを指定します。
1
2
3
4
5
6
7
8
9
class Post < ActiveRecord::Base
belongs_to :blog
scope :of_visible_blog, -> { includes(:blog).references(:blogs).merge(Blog.visible) }
scope :title_of, ->(title) { where(title: title) }
def self.ransackable_scopes(auth_object = nil)
%i(of_visible_blog title_of)
end
上記のように指定すると、次のようにscopeをransackの条件として利用することができるようになります。
1
2
3
Post.ransack(of_visible_blog: true).result
Post.ransack(title_of: "It's a beautiful day").result
Post.ransack(of_visible_blog: true, title_of: "It's a beautiful day").result