Rails ransackとjp_prefectureを利用して都道府県の絞り込み検索を行う
Railsのサービスにransackを利用して検索機能を実装しました。
具体的には、イベント一覧から希望のイベントを検索できるように、 フリーワード検索+jp_prefecture
で都道府県をセレクトして絞り込みできるようにしました。
作成する物
こんなものができました!
手順
gemをインストール
検索フォームを作成するransack
と、都道府県コードから県名を変換するjp_prefecture
を使用します。
gem 'ransack' gem 'jp_prefecture'
ライブラリの読み込み
# app/models/event.rb class Event < ApplicationRecord include JpPrefecture end
DB修正
データベースにイベント開催地(県)を追加します。
この時カラムのタイプは integer か string で作成します。
今回は県名が欲しいのでstringになります。
# マイグレーションファイルの設定 class AddColumnsToEvent < ActiveRecord::Migration[6.0] def change add_column :events, :prefecture, :string end end
検索機能を追加
controllerに設定を追加します。
# app/controllers/events_controller.rb class EventsController < ApplicationController def index # 検索オブジェクト @search = Event.ransack(params[:q]) # 検索結果 @event = @search.result.page(params[:page]).per(30) end end
検索フォームを追加
ransackのヘルパーsearch_form_for
を利用して、viewに設定を追加します。
# app/views/layouts/application.html.slim = search_form_for @search do |f| .form-row.mt-3.mb-3.justify-content-md-center .col-md-4 = f.search_field :title_or_body_cont, class: 'form-control' .col-md-2 = f.collection_select :prefecture_eq, JpPrefecture::Prefecture.all, :name, :name, { include_blank: '開催場所' }, { class: 'custom-select' } .col-md-1 = f.submit '検索', class: 'btn btn-primary'
jp_prefectureについて
上記より抜粋したこの部分は、都道府県のセレクトボックスを作成しています。
= f.collection_select :prefecture_eq, JpPrefecture::Prefecture.all, :name, :name, { include_blank: '開催場所' }, { class: 'custom-select' }
言葉に置き換えるとこのような形です。
= f.collection_select :カラム名_検索マッチャー, オブジェクトの配列, value属性の項目, 表示する項目, { include_blank: '空のオプション' }, { class: 'クラス名' }
collection_select
は、モデルの情報をもとにセレクトボックスを作成してくれるものです。検索マッチャー「_eq」は、完全一致検索を行います。
この場合prefecture_eq
ですので、prefectureに検索文字列と完全一致するものを検索します。:name(value属性の項目)
がDBに送られます。
(今回はDBにstring(name)で登録されているので、こちらもnameになっています):name(表示する項目)
が表示されます。include_blank
は空のオプションを先頭に追加してくれるものです。
検索マッチャーについて
はじめprefecture_eq
部分をprefecture_cont
(like検索)と書いていたのですが、これだと
レコード数が増えた際にDBの負荷が増えてしまう
都道府県のセレクトボックスなので完全一致の方が適切
だということで訂正しました。
より適切なコードを書かないと、別の人が後から見たときに解釈の余地が増えてしまい読み取りに誤解が生じてしまう可能性があるので気をつけたいです。