Created
June 14, 2022 16:50
-
-
Save tk0miya/5e549172e478902ff683304da1c00ced to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
module Ransack | |
module Nullable | |
# Ransack で NULL を含む IN クエリを組み立てるためのヘルパ | |
# | |
# 利用方法: | |
# Ransack::Nullable.build(User, params[:q], nullable: %i[user_id]) | |
# | |
# 注意点: | |
# * フォーム上では NULL を表す値として 'NULL' を送信すること | |
# * FormBuilder#collection_check_boxes() を使う場合、チェックボックスの値には String 型を用いること | |
def build(object, params, nullable: []) # rubocop:disable Metrics/MethodLength | |
queries = {} | |
# *_in 条件を抜き出す | |
nullable.each do |column| | |
key = "#{column}_in" | |
queries[key] = params.delete(key) | |
end | |
q = object.ransack(params) | |
queries.compact.each do |column, values| | |
# 抜き出した *_in 条件を再度組み立てる | |
if values.include? 'NULL' | |
# null を含む場合は (column IN (...) OR column IS NULL) に変換する | |
# 参考: https://github.com/activerecord-hackery/ransack/issues/290 | |
null_column = column.sub(/_in$/, '_null') | |
q.build_grouping({ :m => 'or', column => values.grep_v('NULL'), null_column => true }) | |
else | |
# null を含まない場合は通常通り column IN (...) に変換する | |
q.build_grouping({ column => values }) | |
end | |
# FormBuilder#collection_check_boxes で扱いやすいよう、q.column_in 属性で入力値を返す | |
q.define_singleton_method(column) { values } | |
end | |
q | |
end | |
module_function :build | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment