【Rails】custom predicateについて(ransack)

はじめに

 ransackのcustom predicateとは、name_eqやname_contのeqやcontなどのpredicate(述語)をカスタマイズして、自由に設定できるものです。

実装

まず、config/initializers下にransack.rbファイルを作成しましょう。

公式ドキュメントに下記の記載方法がのっています。

Custom Predicates

# config/initializers/ransack.rb

Ransack.configure do |config|
  config.add_predicate 'equals_diddly', # Name your predicate
    # What non-compound ARel predicate will it use? (eq, matches, etc)
    arel_predicate: 'eq',
    # Format incoming values as you see fit. (Default: Don't do formatting)
    formatter: proc { |v| "#{v}-diddly" },
    # Validate a value. An "invalid" value won't be used in a search.
    # Below is default.
    validator: proc { |v| v.present? },
    # Should compounds be created? Will use the compound (any/all) version
    # of the arel_predicate to create a corresponding any/all version of
    # your predicate. (Default: true)
    compounds: true,
    # Force a specific column type for type-casting of supplied values.
    # (Default: use type from DB column)
    type: :string,
    # Use LOWER(column on database).
    # (Default: false)
    case_insensitive: true
end

一つずつ解説していきます。

# こちらでブロックを作ります。
Ransack.configure do |config|

#ここでpredicateの名前を決めています。これを実際のビューとかで使われるわけですね。
config.add_predicate 'equals_diddly' 

# どんな動きをするかを指定
arel_predicate: 'eq' 

# vが検索されて受け取る値になります。{ |v| "#{v}-diddly" }このブロック内で自分で自由にフォーマットを変えることができます。
formatter: proc { |v| "#{v}-diddly" }

# こちらでバリデーションを決めています。
validator: proc { |v| v.present? } 

# これは恐らく複数のarel_predicateの組み合わせをtrueにするかということだと思います。デフォルトはtrueなので、特にあまりいじらなくて良いかと思います。
compounds: true 

# stringやintegerなどのタイプを指定します。
type: :string 

#  大文字、小文字の区別をする設定です。デフォルトはfalseです。
case_insensitive: true

このような記法で設定していきます。

例えば、

作成日の範囲指定では、掲示板の作成日に対して「◯◯月◯◯日〜◯◯月◯◯日」という検索をかけたいとき、

<%= f.date_field :created_at_gteq, class: 'form-control' %> 〜 
<%= f.date_field :created_at_lteq, class: 'form-control' %> 

これでは、1/1〜1/31日の午前0時まで間しか検索できません。

よって、lteqをカスタマイズします。

ransack.rb

Ransack.configure do |config|
  config.add_predicate 'lteq_end_of_day', # 述語の名前
                                        arel_predicate: 'lteq', #lteqを使用
                                        formatter: proc { |v| v.end_of_day } #上記のものをカスタマイズ
end

これで

<%= f.date_field :created_at_gteq, class: 'form-control' %> 〜 
<%= f.date_field :created_at_lteq_end_of_day, class: 'form-control' %> 

と実装すれば、1/1から1/31日23時59分までの検索をすることができます。