タスク一覧画面に検索機能を実装する(ransack)
検索機能の実装について勉強したので、アウトプットしたいと思います!
目標
「タスク一覧画面に検索機能を追加」
やること
・Ransackのインストール
・名称による検索機能の実装
・登録日時による検索機能の実装
・検索条件を絞る
本題
・Ransackのインストール
Gemfileに「gem 'ransack'」を入力し、bundlerで「bundle」を実行。
・名称による検索機能の実装
ransackをインストールするとransackメソッドがモデルに追加される。
ransackメソッドを使用して、コントローラを修正する。
def index
@q = current_user.tasks.ransack(params[:q]) @tasks = @q.result(distinct: true).recent ... end
タスク一覧画面に検索フォームを作成する。
ranscakによりsarch_form_forという検索フォームを作成されるヘルパーが提供される!
h1 タスク一覧 = search_form_for @q, class: 'mb-5' do |f| .form-group.row = f.label :name_cont, '名称', class: 'col-sm-2 col-form-label' .col-sm-10 = f.search_field :name_cont, class: 'form-control'
.form-group
= f.submit class: 'btn btn-outline-primary' = link_to '新規登録', new_task_path, class: 'btn btn-primaty mb-3'
※ranscakを利用する際は、検索フィールドの名前を一定のルールに従ってつける。
今回は名称に「検索フォームで入力した文字が含まれている」という検索を実現したいので「name_cont」という名前をつける。
検索時のSQLを調べると、PostgreSQLのILIKE(大文字と小文字の区別をしない)が使われていた。これは検索フィールドの名前を「name」にした結果である。
また「_cont」は、検索文字列を含むものを検索するransackが用意したマッチャー。
よって「name_cont」を検索フォームの名前にすることで、入力した文字列を含むタスクを検索できるようになる。
・登録日時による検索
タスク一覧の検索フォームに登録日時のフィールドを追加する。
h1 タスク一覧
= search_form_for @q, class: 'mb-5' do |f|
.form-group.row
= f.label :name_cont, '名称', class: 'col-sm-2 col-form-label'
.col-sm-10
= f.search_field :name_cont, class: 'form-control'
.form-group.row
= f.label :created_at_gteq, '登録日時', class: 'col-sm-2 col-form-label'
.col-sm-10
= f.search_field :created_at_gteq, class: 'form-control'
.form-group
= f.submit class: 'btn btn-outline-primary'
= link_to '新規登録', new_task_path, class: 'btn btn-primary mb-3'
登録日時検索フィールドで使用した_gteqは、greater than or equalの略で、「入力した値より大きいか同じ」なものを検索する。
日時の場合は、「同じ日にちかそれより未来の日にち」を検索する。
登録日時の検索後のSQLでは、比較演算子の「>=」が使われている!
・検索条件を絞る
どうやらユーザーが意図的にパラメータを加工すると、他のカラムを使った検索ができてしまうらしい。
それを防ぐために、検索結果に制限をかける。
app/models/task.rb
class Task < ApplicationRecord def self.ransackable_attributes(auth_object = nil) %w[name created_at] end def self.ransackable_associations(auth_object = nil) [] end ... end
ransackable_attributesで、検索対象にすることを許可するカラムを指定する。
nameとcreate_atを指定することで、他のデータを検索フォームに入力しても無視される。
ransackable_associationsは、検索条件に含める関連を指定できる。
このメソッドを空の配列を返すようにオーバーライドすることで、検索条件に意図しない関連を含めないようにすることができる。
まとめ
・ransackをインストール
・ransackメソッドを使って、コンソールの編r集
・search_form_foを使い、ビューに検索フォームを作成する。
・rasackable_attributes, ransackable_associationsメソッドで検索条件をつける。
ransackめちゃめちゃ便利!!