2つのカスタムバリデーターを1つのメソッド内で処理する方法

カスタムバリデーターは独自のバリデーションを作れるものです。 今まで一つのバリデータを作るたびに1ファイル作成してたのですが、大変非効率だと思っていた所先輩が教えてくれたので共有します。

モデルは銀行口座の管理を行うものです。bank_codeは銀行コード, bank_branch_codeには銀行支店コードが入る想定です。入力フォームでbank_code, bank_branch_codeのいずれかに不正な番号が入力された際に(そのコードは存在しませんよーという)バリデーションを発動させます。

app/models/control_trading_account.rb

ここではカスタムバリデーターを使いますよという合図を出す
class ControlTradingAccount < ApplicationRecord
  validates :bank_code,          presence: true, exist_association: { key: :code, model: 'Bank' } # このBankクラスをバリデーターメソッドに渡したい
  validates :bank_branch_code,   presence: true, exist_association: { key: :code, model: 'BankBranch' }# このBankBranchをバリデーターメソッドに渡したい
end

app/validators/exist_association_validator.rb

さっきまではこれと同じようなメソッドを2つ書いていました....orz
一つのメソッドで2つの処理を実現させるためには、この中で上のBankBankBranchを受け取る!
class ExistAssociationValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    model = options[:model].safe_constantize  # optionsでパラメータを受け取れるとのこと! safe_constantizeは文字列処理
    unless model.find_by(options[:key] => value)  # model変数にBankとBankBranchがそれぞれ入ります
      record.errors[attribute] << (options[:message] || '正しくありません')
    end
  end
end

バリデーターに限らず、optionでパラメーターを取得するのは今後多用しそうなので備忘録としての投稿でしたー。

ごいすー