概要
ActiveRecordを継承したモデルでバリデーションエラーを発生させた際に、特定のバリデーションに反応したのか判定する
どういうときに使うかと言うと、具体的な例を挙げると、valid?とかsave際にある属性の空文字チェックでエラーになっているかどうかというようなことを調べる
前提条件
Rails: 5.2
Ruby: 2.5.1
本題
サンプルのユーザテーブルの定義
create_table :users do |t|
t.string :name
t.timestamps
end
ユーザモデルの定義
nameの空文字チェックのバリエーションがある
class User < ApplicationRecord
validates :name, presence: true
end
まずはインスタンス化してバリデーションチェック
> u = User.new
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
> u.valid?
=> false
エラーを確認すると、デフォルトの空文字のエラーメッセージが表示されるのがわかる
> u.errors.full_messages
=> ["Name can't be blank"]
added?メソッドを使うと特定の属性のどのバリデーションエラーが起こったかどうか調べることができる(本投稿のコメント欄より)
# 引数には属性名のシンボルとバリデーションエラーの種類を指定してあげる
> u.errors.added?(:name, :blank)
=> true
# 2つ目の引数を指定しないとデフォルト値が 2つ目の引数は:invalidなので注意が必要
> u.errors.added?(:name)
=> false
[おまけ]バリデーションエラーの詳細を取得する
エラーの一覧が欲しい場合は、errors.detailsを実行すると、どの要素のどのバリデーションのエラー内容 :blankがあることがわかる
> u.errors.details
=> {:name=>[{:error=>:blank}]}
# シンボルを指定してあげるとオブジェクトの配列を返す
u.errors.details[:name]
=> [{:error=>:blank}]
# 適当なシンボルを入れると空の配列を返す
> u.errors.details[:name_xxxx]
=> []
このようにdetailsからシンボルを指定してその返す配列の中に特定のシンボル:blankの存在をチェックすれば
added?のように特定のバリデーションに反応したのかどうか判定することもできる
> u.errors.details[:name].any? { |d| d[:error] == :blank }
=> true