LoginSignup
17
13

More than 5 years have passed since last update.

ActiveModel::Errorsのエラーメッセージをエラータイプにしたい

Last updated at Posted at 2015-07-10

APIとか作ってると、パラメータエラーのときのレスポンスに困る。
エラーメッセージやら多言語対応などあんまり考えたくない。

そこでバリデーションはActiveModelValidatorにぜんぶお任せしたいし、サーバ側に極力View要素のロジックを持たせたくないので、エラーメッセージに関してもクライアント側で制御して欲しい。

各Validatorにはエラーメッセージが用意されているor再定義できるが、デフォルトのエラーメッセージを使ってクライアント側で制御するには扱いにくく、すべてを再定義するのもめんどうなのでエラータイプを利用したい。

何のことかいまいち伝えにくいので具体的に。

Userモデルにnameのバリデーションを定義して説明してみる。

user.rb
class User < ActiveRecord::Base
  validates :name,
    presence: true,
    uniqueness: { :case_sensitive => false },
    length: { in: 4..30 },
    format: { with: /\A[a-zA-Z][\w]{3,29}\z/ }
end

エラーメッセージは、以下のようなやつ。

  • can't be blank
  • has already been taken
  • is too short
  • is invalid

エラータイプは、以下のようなやつ。

  • blank
  • taken
  • too_short
  • invalid

デフォルト状態のエラーメッセージを出力してみる。

> user = User.new
> user.validate
> user.errors.messages
=> {:name=>["can't be blank", "is too short (minimum is 4 characters)", "is invalid"]}

user.errorsからtypeを引き出すうまい方法がわからなかったので(※情報求む!)、ActiveModel::Errorsを読んで、generate_messageメソッドに細工する。

config/initializers/active_model/errors.rbを追加。

config/initializers/active_model/errors.rb
module ActiveModel
  class Errors
    # Change error message to error type
    def generate_message(attribute, type = :invalid, options = {})
      type
    end
  end
end

エラータイプを返すようになる

> user = User.new
> user.validate
> user.errors.messages
=> {:name=>[:blank, :too_short, :invalid]}

これでクライアント側は各キーに対応するメッセージを出しやすくなる。

それにしてもこれでは対応が無骨にすぎる。
validatesのオプションであるmessageを定義したりできないし、まぁタイプを返したいんだから使わないんだけれども。。
user.errors.typesとかuser.errors.types_with_messageなどで取り出せるようにしたいところ。

17
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13