ActiveModel の errors.messages に入ってるエラーメッセージが、どの validation でひっかかったかテストで知りたい。

ActiveModel の errors.messages に入ってるエラーメッセージが、どの validation でひっかかったかテストで知りたい。

という思いがずっと前からあって下記エントリーのような対応をしていました。

Rails 触りはじめのエントリーでとても懐かしい。

それはいいとして expect(model.errors_on(:attribute)).to include("can't be blank")みたいのは絶対に書きたくなかったのでおおむね満足していましたが、これレイルウェ~イから逸脱しすぎで全くよくないよねって思い至ったので、テスト時のみわかればいいやと思って model 側を触らないような対応をしました。

spec/rails_helper.rb とかその他ふさわしい場所に追加。

module ActiveModel
  module Validations
    def has_error_on(attribute, error)
      self.valid?
      self.errors.messages[attribute].try(:include?, error)
    end
  end


  class Errors
    def generate_message(attribute, type = :invalid, options = {})
      message_table[type] || type
    end


    def message_table
      {
          present: :absence,
          accepted: :acceptance,
          invalid: :format,
          not_a_number: :numericality,
          not_an_integer: :numericality,
          blank: :presence,
      }
    end
  end
end

generate_messageI18n にわたして翻訳とかするんですがそれはテストではいらないので翻訳につかうキーをそのまま返すようにしました。message_table メソッドは validator の名前と関係ないシンボルを渡す(なんでやねん)のがいくつかあったのでそれ戻す用です。

expect(model.has_error_on(:name, :presence)).to be_truthy って感じの書けばテストできておおむね満足しました。