Messages
Messages in failure API can be set in 4 different ways:
- By passing a message string explicitly - the simplest way; however, using locales is a cleaner solution even if you don't have a multi-language system
- By passing a message
identifier
that will be used to retrieve a corresponding message template that will be evaluated using provided (optional) data - By passing a hash with message text and arbitrary meta-data - this can be useful when you want to provide additional information in addition to message text, ie error codes etc.
Examples in this section will use
key
failures exclusively, but keep in mind that the exact same API is available when you usebase
failures
Explicit messages
To set a failure message explicitly, pass a message string:
class NewUserContract < Dry::Validation::Contract
params do
required(:age).value(:integer)
end
rule(:age) do
key.failure('must be greater than 18') if values[:age] < 18
end
end
contract = NewUserContract.new
contract.call(age: 17).errors.to_h
# => {:age=>["must be greater than 18"]}
Passing additional meta-data
If you want to set additional meta-data, pass a hash with :text
key:
class NewUserContract < Dry::Validation::Contract
params do
required(:age).value(:integer)
end
rule(:age) do
key.failure(text: 'must be greater than 18', code: 123) if values[:age] < 18
end
end
contract = NewUserContract.new
contract.call(age: 17).errors.to_h
# => {:age=>[{:text=>"must be greater than 18", :code=>123}]}
Using localized messages backend
If you enable the :i18n
or :yaml
messages backend in the configuration, you can define messages in a yaml file and use their identifiers instead of plain strings. Here's a sample yaml with a message for our age
error:
en:
dry_validation:
errors:
rules:
age:
invalid: 'must be greater than 18'
Provided we configure our contract to use a custom messages file, we can now write this:
class NewUserContract < Dry::Validation::Contract
params do
required(:age).value(:integer)
end
rule(:age) do
key.failure(:invalid) if values[:age] < 18
end
end
contract = NewUserContract.new
contract.call(age: 17).errors.to_h
# => {:age=>["must be greater than 18"]}
Using :full
option with a translated key
If you want to have key names included in the generated messages, you can use full
option. It requires you to include localized key names in your messages yaml config. Let's say you have a key called :name
and you want it to appear as "First name"
:
en:
dry_validation:
rules:
name: "First name"
Then, you can simply use the full
option to get the key translated and included in error messages:
class NewUserContract < Dry::Validation::Contract
params do
required(:name).filled(:string)
end
end
contract = NewUserContract.new
contract.call(name: "").errors(full: true).to_h
# => {:name=>["First name must be filled"]}
Schema messages use the same top-level namespace as rule messages, remember about this if you want to customize messages for schema predicate failures.