検索機能

ransackによる検索機能

gem 'ransack'
% bundle install

検索結果を一覧表示するためのアクション

# person_controller.rb

def index
  @q = Person.ransack(params[:q])  # 送られてきたパラメータをもとにレコードを検索する
  @people = @q.result(distinct: true) # 検索したレコードをActiveRecord::Relationのオブジェクトに変換する
  # distinct:trueは検索結果のレコードの重複を除く(関連テーブルの情報を絞り込み条件とする時など)
end

ビューの記法

  1. search_form_for で検索用フォームを作り、@qを渡す(検索パラメータparams[:q]がコントローラに送られる)
  2. マッチャ(インスタンスの属性名_述語)で、あいまい検索や範囲指定などの検索オプションを指定できる。
<%= search_form_for @q do |f| %>
  <!-- 属性名_述語 -->
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont %>

  <!-- 複数の属性について検索条件をつけるとき -->
  <%= f.label :name_or_description_or_email_or_articles_title_cont %>
  <%= f.search_field :name_or_description_or_email_or_articles_title_cont %>

  <%= f.submit %>
<% end %>
<!-- params[:q][:name_cont]などが取得できる -->

述語(predicate)一覧 https://github.com/activerecord-hackery/ransack#search-matchers

述語のカスタマイズ

カスタマイズする述語を選び、どうフォーマットするかをprocオブジェクトで記述する。

# config/initializers/ransack.rb

Ransack.configure do |config|
  config.add_predicate 'lteq_end_of_day', # 述語名
    # どの述語をカスタマイズする? (eq, matches, etc)
    arel_predicate: 'lteq',
    # どのようにフォーマットする?
    formatter: proc { |v| v.end_of_day },

    # バリデーション. 不正な検索条件にならないよう.
    # Below is default.
    validator: proc { |v| v.present? },

    # よくわからん(https://github.com/activerecord-hackery/ransack/issues/45)
    #  (Default: true)
    compounds: true,

    # データ型は?
    # (Default: use type from DB column)
    type: :string,

    # 大文字小文字の違いを無視する?(大文字を小文字に直す)
    # (Default: false)
    case_insensitive: true
  end
end

:created_at_lteq では基準が00:00になり当日分のレコードが引っかからない
:created_at_lteq_end_of_day では基準が23:59になり当日分も引っかかる