LoginSignup
1
0

ransack でカラム同士を比較する

Last updated at Posted at 2020-08-14

まとめ

下記の ransacker とパラメータの組み合わせで (model.column_A <= model.column_B) = TRUE が条件に追加されます。同じテーブルのカラム同士の比較を条件に加えることができます。

モデルに書くransacker
ransacker "compare", args: %i[parent ransacker_args] do |parent, args|
  columns = args.values
  Arel::Nodes::Grouping.new(
    Arel::Nodes::InfixOperation.new(
      '<=',
      parent.table[columns[0].to_sym], parent.table[columns[1].to_sym]
    )
  )
end
パラメータ
'q' => {
    'c' => {
        '0' => {
            'a' => {'0' => {'name' => 'compare',
                            'ransacker_args' => {
                                '0' => 'column_A',
                                '1' => 'column_B'
                            }
            }
            },
            'p' => 'true',
            'v' => {'0' => {'value' => 1}
            }
        }
    }
}

v3.2.1 で動作することを確認してます。
https://github.com/activerecord-hackery/ransack/releases/tag/v3.2.1
v4.0.0 以降は未検証。

解説

ransacker

ransacker "compare", args: %i[parent ransacker_args] do |parent, args|
  columns = args.values
  Arel::Nodes::Grouping.new(
    Arel::Nodes::InfixOperation.new(
      '<=',
      parent.table[columns[0].to_sym], parent.table[columns[1].to_sym]
    )
  )
end

ransacker で追加の ransack 用のメソッドを用意してあげます。
args: %i[parent ransacker_args]ransacker_args を使えるようにして、ブロック引数にも args を書いて、ブロックの中で使えるようにします。
Arel::Nodes::Grouping() に引数の結果を収めてくれます。これを書かないと SQL の式が成り立たないです。
Arel::Nodes::InfixOperation は第一引数に演算子をとって、第二引数と第三引数を演算する式を返します。
この ransacker は (model.column_A <= model.column_B) という式を作ります。

パラメータ

'q' => {
    'c' => {
        '0' => {
            'a' => {'0' => {'name' => 'compare',
                            'ransacker_args' => {
                                '0' => 'column_A',
                                '1' => 'column_B'
                            }
            }
            },
            'p' => 'true',
            'v' => {'0' => {'value' => 1}
            }
        }
    }
}

Advanced Mode を使います。
比較するだけなので p や v は不要に思えますが、a p v の3つが揃わないと ransack が条件として追加してくれないようなので p や v も書きます。
a の name には素直に追加した ransacker のメソッド名を書きます。
ransacker_args には比較したいカラムを書きます。
p は true、value は 1 にします。でも、value は何でもいいです。

考察

ransacker_args を使わないと、比較するカラムの組み合わせの数だけ ransacker を書かないといけなくなりますが、このように ransacker_args を使えばコンパクトに書けます。
便利ですね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0