Chiroru's Diary

日々の学びをちょこちょこメモしていきます

Rails ransackとjp_prefectureを利用して都道府県の絞り込み検索を行う

Railsのサービスにransackを利用して検索機能を実装しました。

具体的には、イベント一覧から希望のイベントを検索できるように、 フリーワード検索+jp_prefecture都道府県をセレクトして絞り込みできるようにしました。

作成する物

こんなものができました!

f:id:chiroru_memo:20200717130334g:plain
検索フォーム

手順

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の負荷が増えてしまう

  • 都道府県のセレクトボックスなので完全一致の方が適切

だということで訂正しました。

より適切なコードを書かないと、別の人が後から見たときに解釈の余地が増えてしまい読み取りに誤解が生じてしまう可能性があるので気をつけたいです。

参考