Error messages
By default dry-schema
comes with a set of pre-defined error messages for every built-in predicate. They are defined in a yaml file which is shipped with the gem. This file is compatible with I18n
format.
Configuration
You can provide your own messages and configure your schemas to use it like that:
schema = Dry::Schema.Params do
config.messages.load_paths << '/path/to/my/errors.yml'
end
You can also provide a namespace per-schema that will be used by default:
schema = Dry::Schema.Params do
config.messages.namespace = :user
end
You can change the default top namespace using:
schema = Dry::Schema.Params do
config.messages.top_namespace = :validation_schema
end
Lookup rules
en:
dry_schema:
errors:
size?:
arg:
default: "size must be %{num}"
range: "size must be within %{left} - %{right}"
value:
string:
arg:
default: "length must be %{num}"
range: "length must be within %{left} - %{right}"
filled?: "must be filled"
included_in?: "must be one of %{list}"
excluded_from?: "must not be one of: %{list}"
rules:
email:
filled?: "the email is missing"
user:
filled?: "name cannot be blank"
rules:
address:
filled?: "You gotta tell us where you live"
Given the yaml file above, messages lookup works as follows:
messages = Dry::Schema::Messages::YAML.load(%w(/path/to/our/errors.yml))
# matching arg type for size? predicate
messages[:size?, rule: :name, arg_type: Fixnum] # => "size must be %{num}"
messages[:size?, rule: :name, arg_type: Range] # => "size must be within %{left} - %{right}"
# matching val type for size? predicate
messages[:size?, rule: :name, val_type: String] # => "length must be %{num}"
# matching predicate
messages[:filled?, rule: :age] # => "must be filled"
messages[:filled?, rule: :address] # => "must be filled"
# matching predicate for a specific rule
messages[:filled?, rule: :email] # => "the email is missing"
# with namespaced messages
user_messages = messages.namespaced(:user)
user_messages[:filled?, rule: :age] # "cannot be blank"
user_messages[:filled?, rule: :address] # "You gotta tell us where you live"
By configuring load_paths
and/or namespace
in a schema, default messages are going to be automatically merged with your overrides and/or namespaced.
I18n integration
If you are using i18n
gem and load it before dry-schema
then you'll be able to configure a schema to use i18n
messages:
require 'i18n'
require 'dry-schema'
schema = Dry::Schema.Params do
config.messages.backend = :i18n
required(:email).filled(:string)
end
# return default translations
schema.call(email: '').errors.to_h
{ :email => ["must be filled"] }
# return other translations (assuming you have it :))
puts schema.call(email: '').errors(locale: :pl).to_h
{ :email => ["musi być wypełniony"] }
Important: I18n must be initialized before using a schema, dry-schema
does not try to do it for you, it only sets its default error translations automatically.
Full messages
By default, messages do not include a rule's name, if you want it to be included simply use :full
option:
schema.call(email: '').errors(full: true).to_h
{ :email => ["email must be filled"] }
Finding the right key
dry-schema
has one error key for each kind of validation (Refer to errors.yml
for the full list). key?
and filled?
can usually be mistaken for each other, so pay attention to them:
key?
: a required parameter is missing in theparams
hash.filled?
: a required parameter is in theparams
hash but has an empty value.