【Ruby on Rails】Ransackで簡単に検索フォームを実装する

Ruby on Rails

ransackとは

Ruby on Railsでシンプルかつ高度な検索フォームを簡単に実装できるgemです。

インストール

公式の手順でインストールしていきます。

gem 'ransack'
$ bundle install

使用方法

Ransackは、シンプルモードとアドバンスドモードの2つのモードで使用できますが、簡単なシンプルモードの使い方を説明します。

例として、記事を検索できる検索フォームを実装します。

コントローラーを編集

まず、検索フォームを実装したいコントローラとそのアクションに以下のコードを記載します。

  def index
    @q = Post.ransack(params[:q])
    @posts = @q.result.includes(:user, :favorites).order(created_at: :desc)
  end

Ransack固有のメソッドがいくつかあります。

params[:q]:後ほど説明する検索フォームでの入力した値を受け取ります。値はハッシュで入っています。

Post.ransack(prams[:q]):検索フォームの条件、入力した値(params[:q])を元に、postsテーブルからデータを検索します。データの検索条件はオプションで指定できます(公式参照)。

@q.resultransackメソッド取得したデータ(Ransack::Searchオブジェクト)を元に、ActiveRecord_Relationオブジェクトに変換します。

ビューを編集

次にviewで検索フォームを作成します。

記事一覧画面で検索したいので、index.html.slimを編集します。

p 記事検索
= search_form_for @q do |f|
  = f.search_field :user_name_cont, placeholder: 'ユーザー名'
  = f.search_field :title_cont, placeholder: '記事のタイトル'
  = f.search_field :content_cont, placeholder: '記事の内容'

  = f.submit

search_form_for:Railsのフォームヘルパーメソッドであるform_forform_withメソッドのransack版です。

f.search_field:htmlで<input type="search">に変換されます。

title_conttitleカラムから_contという条件で検索するよという条件を指定します(検索するのはコントローラー内)。_contは入力した値が含まれる(SQLのWHERE LIKE)という条件。user_name(usersテーブルのnameカラム)のように関連のある検索もできます。

@q:入力した値、条件などの情報が入ります。prams[:q]で受け取れます。


下記の画像のようなフォームが表示されます。

f.labelでラベルも作成できますが、今回は邪魔だったので、placeholderを使ってフォームを識別しています。

実装完了

試しに、記事のタイトルに「test」を入力して、検索してみます。正しく動けば右側の記事のみ表示されます。

ちゃんと検索できています。

動作確認

では、コントローラー内でどのような動きをしているか細かく見ていきます。

まず、コントローラーで検索フォームに入力した検索条件を受け取ります。

params[:q] 
#=> <ActionController::Parameters {"user_name_cont"=>"", "title_cont"=>"test", "content_cont"=>""} permitted: false>

params[:q]には、"title_cont"=>"test"という検索条件が入っています。

@q = Post.ransack(params[:q])
#=> Ransack::Search<class: Post, base: Grouping <conditions: [Condition <attributes: ["title"], predicate: cont, values: ["test"]>], combinator: and>>

@qには、title名に「test」が含まれるpost(記事)の検索結果がRansack::Searchオブジェクトで入っています。

<conditions: ~~~~ 内に条件が指定されています。

@posts = @q.result
#=> SELECT  "posts".* FROM "posts" WHERE "posts"."title" LIKE '%test%' LIMIT ?  [["LIMIT", 11]]
#=> <ActiveRecord::Relation [#<Post id: 1, title: "test", content: "テストテスト", post_image: nil, user_id: 1, created_at: "2022-01-02 10:33:30", updated_at: "2022-01-02 10:33:30">

@postには、@q.result@qの情報からSQLクエリを発行し、その結果がActiveRecord::Relationオブジェクトで入っています。

ちなみに検索条件が無い場合(nil)は、Post.allと同じ動きをします。

検索結果がビューで表示されます。

以上

まとめ

簡単に検索フォームが実装できました。

ここでは紹介できなかったソート機能や詳細設定、多くの検索オプションなどがありますので、一度公式に目を通してみてください。

GitHub - activerecord-hackery/ransack: Object-based searching.
Object-based searching. . Contribute to activerecord-hackery/ransack development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました