Techioz Blog

列の値が文字列内に含まれているかどうかを確認する方法

概要

会社の銀行口座で支払いが受け取られると、アプリケーションに対して Webhook がトリガーされ、支払いラベルを含む支払いに関連するデータが提供されます。

このラベルはクライアントによって書き込まれた文字列であり、インスタンスごとに大幅に異なる場合があります。通常、ラベルに含める参照をクライアントに提供して、クライアントを識別できるようにします。参照パターンは、正規表現 /-?-?-?/ に準拠します。例: 「ABCDE-2023-01-0001」または「ab-2023-01-0001」など。

さらに、number とmoneyin_key という 2 つの列を持つ Invoice モデルがあります。通常、数値は次の形式に従います: ABCDE-2023-01-0001。moneyin_key 値は同じですが、ハイフンがありません (「ABCDE2023010001」のように)。

クライアントが提供したラベルに関連するすべての請求書を取得するスコープを作成したいと考えています。前述したように、ラベルは大きく異なる場合がありますが、例を次に示します。「VIR. O/ JUMBO VISMA MOTIF: EDP2023100001」 私のスコープは次のように構成されている必要があります。

scope :related_to_payment_label, -> (label) { do_something_here }

いくつかのアプローチを試しましたが、どれも成功しませんでした。例:

scope :related_to_payment_label, -> (label) {
  where("number ILIKE :label OR moneyin_key ILIKE :label", label: "%#{label}%")
}

何か案は?

解決策

ここでは次のように REGEXP 関数を使用できます。

scope :related_to_payment_label, -> {
  where("number REGEXP :regexp OR moneyin_key REGEXP :regexp", regexp: '[a-zA-Z]{2,5}-?\d{4}-?\d{2}-?\d{4}\z')
}

または、データベースが Postgres の場合は、大文字と小文字を区別しない正規表現には ~* を使用し、大文字と小文字を区別するには ~* を使用することもできます。

例えば:

scope :related_to_payment_label, -> {
  where("number ~* :regexp OR moneyin_key ~* :regexp", regexp: '[a-zA-Z]{2,5}-?\d{4}-?\d{2}-?\d{4}\z')
}