※ Rails5でのActiveModelの話
class User < ActiveRecord::Base validates :name, presence: true, uniqueness: true, length: { minimum: 2, maximum: 20 } end
こんな感じのモデルがあったとして
> user = User.new > user.tap(&:validate).errors.messages # => {:name=>["can't be blank", "is too short (minimum is 2 characters)"]}
入力に不備があると ActiveModel::Errors
インスタンスでエラー内容が参照できる
今回は特定のバリデーション(例えば今回の例だとlengthのminimum
にかかった時など)にかかった時の分岐を考える
愚直にかけばこうなる
if user.tap(&:validate).errors[:name].include?('is too short (minimum is 2 characters)') # something end
I18nとかで :en
があったり :ja
など複数扱う場合だとこれでは :ja
のときにかからない
しかしこれはRailsの4系までの話
Rails5のActiveModelからはdetailsというメソッドがはえておりどのバリデーションにかかったのかのtypeを返してくれる
⇓の中盤より少し下にAdd ActiveModel::Errors#details
として書いてある
rails/CHANGELOG.md at v5.0.0 · rails/rails · GitHub
このdetails
を使うと下記のようなvalidatorのtypeがかえってくる
> user.tap(&:validate).errors.details # => {:email=>[{:error=>:blank}], :password=>[{:error=>:blank}], :name=>[{:error=>:blank}, {:error=>:too_short, :count=>2}]}
typeなのでi18nとかに左右されて変わらないので、先程ほどの特定のバリデーションにかかった時の分岐は
if user.tap(&:validate).errors.details[:name].any? { |e| e[:error] == :too_short } # something end
のように書ける
余談
このdetailsをRails4.xとかでも使えるようにするgemは存在するようです