APIとか作ってると、パラメータエラーのときのレスポンスに困る。
エラーメッセージやら多言語対応などあんまり考えたくない。
そこでバリデーションはActiveModel
のValidator
にぜんぶお任せしたいし、サーバ側に極力View要素のロジックを持たせたくないので、エラーメッセージに関してもクライアント側で制御して欲しい。
各Validatorにはエラーメッセージが用意されているor再定義できるが、デフォルトのエラーメッセージを使ってクライアント側で制御するには扱いにくく、すべてを再定義するのもめんどうなのでエラータイプを利用したい。
何のことかいまいち伝えにくいので具体的に。
User
モデルにname
のバリデーションを定義して説明してみる。
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
を追加。
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
などで取り出せるようにしたいところ。