gem 'ransack'について
最終課題で追加実装として用意されていた項目で、実際のアプリケーションに落とし込むところまで行けなかったのですが、気になったまま放置していたものがあったので、今回はそれについて書いてみようと思います。
gem 'ransack'
ですが、ザックリと言うと検索機能用に用意されたgemのようです。
何がしかのwebアプリで検索は使うことがあるので、使えるようになっておくと良いのかなと思います。
導入方法
gemの導入はいつもの流れ
公式GitHubによると互換性のあるバージョンはRuby2.3以降のRails5.0, 5.1, 5.2, 6.0のようです。
# Gemfile gem 'ransack'
Gemfileに記入後にターミナルで
% bundle install
を実行。
ransackは検索機能なので実装時にはテスト用にダミーデータが必要。
実装において検索機能はアクションで記述していく。
通常手書きで検索機能を実装する時、ヘッダーバー(application.html.erb)などのように複数のページに跨いで検索機能が実行される場合は、DBのデータを直接操作するのでモデルにメソッドを書くことが多かったですが、ransack
を使用した時はこの辺りは少し変わってます。
GitHubによればSimpleモードの利用においては特にセットアップは殆ど必要なくそのまま使える。
メタサーチの場合はいくつかのことに注意する必要がある。
- 検索パラメーターのデフォルトのパラメーターキーは、:searchではなく:qになりました。これは主にクエリ文字列を短くするためですが、高度なクエリ(下記)は、ほとんどのブラウザでURLの長さの制限に違反するため、HTTP POSTリクエストへの切り替えが必要です。このキーは構成可能です。
- form_forはsearch_form_forになり、Ransack :: Searchオブジェクトが渡されていることを検証します
- Common ActiveRecord :: Relationメソッドは、検索オブジェクトによって委任されなくなりました。代わりに、Ransack#resultを呼び出して検索結果(ActiveRecordアダプターの場合はActiveRecord :: Relation)を取得します。
※ 公式GitHubより引用
# 検索を行う対象controller def search @search = Product.ransack(params[:q]) @search_products = @search.result(distinct: true) end
ransackメソッド
を利用するにはparams
では[:q]と指定してやる必要がある、これは引用によれば元々は[:search]だったとありますね。
取得された変数に対してresultメソッド
を使用することで検索結果を出力することができる。
distinct: true
オプションをつけることで重複する内容を省きます。
関連する別のテーブルでソートする場合は
@search_products = @search.result(distinct: true).includes(:user)
のように記述しページネーションを利用している場合はさらに.page(params[:page]).per(5)
で1ページ辺り5件表示されるようになる。
viewではform_for
ヘルパーではなく、search_form_for
と言うのを使用する。
ransack
では主要で使えるビューヘルパーが2種類あり、もう一つはsort_link
というそうです。
.search_wrapper = search_form_for @search do |f| = f.label :name_cont = f.search_field :name_cont, placeholder: 検索するキーワードを入力 = f.submit '検索'
検索フィールドで使用しているsearch_field
の引数は:属性名
の形か、:name_or_email_cont
のように指定することで複数のカラムを検索することもできる。
公式ドキュメントにある_predicate
の部分は検索する時のSearch Matchersという検索述語のこと。
今回使用している_cont
は検索したキーワードを含む(部分一致)か、という条件。
今回のように基本アクション以外を使っている場合はルーティングは別途用意する
「route.rb」 resources :product do collection do get :search end end
sort_link
ヘルパーはテーブルヘッダーを作成する。並べ替えの条件が複雑な場合はmodelクラスでscope
を使って設定するみたいです。
ソートが必要ない場合は使わなくても大丈夫ですね。
@search_products
を表示できるようにviewに書いておけばOK。
検索をかけて該当した場合、該当しない場合、検索してない場合で用意する。
参考にさせていただいた記事
公式GitHub
[Rails5]ransackってなんぞ?
【Ruby on Rails】gem 'ransack' を利用した検索機能/フォームの実装
色々なマッチャが使用できるので検索機能を使う時は利用していきたいです。
したらな❗️ 👋