A note of a person who is learning programming, SakaTaQ

ロック好きのプログラミング学習

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モードの利用においては特にセットアップは殆ど必要なくそのまま使える。
メタサーチの場合はいくつかのことに注意する必要がある。

  1. 検索パラメーターのデフォルトのパラメーターキーは、:searchではなく:qになりました。これは主にクエリ文字列を短くするためですが、高度なクエリ(下記)は、ほとんどのブラウザでURLの長さの制限に違反するため、HTTP POSTリクエストへの切り替えが必要です。このキーは構成可能です。
  2. form_forはsearch_form_forになり、Ransack :: Searchオブジェクトが渡されていることを検証します
  3. 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' を利用した検索機能/フォームの実装


色々なマッチャが使用できるので検索機能を使う時は利用していきたいです。

したらな❗️ 👋