Move Rails validation message into localization en.yml - ruby-on-rails

I'm seeing linting errors from Rubocop and I'm not quite sure how to fix one:
Example taken from Rubocop for Rails/i18nLocaleTexts
# bad
class User < ApplicationRecord
validates :email, presence: { message: "must be present" }
end
# good
# config/locales/en.yml
# en:
# activerecord:
# errors:
# models:
# user:
# blank: "must be present"
class User < ApplicationRecord
validates :email, presence: true
end
But what if the error is on a uniqueness validation in the Department model like:
# app/models/department.rb
...
validates :role, uniqueness: { scope: :company, message: 'admin is already present' }, if: -> { role_admin? }
Tried:
# en.yml
activerecord:
errors:
models:
publication:
attributes:
base:
must_be_in_future: Release date must be in future
department:
uniqueness: admin is already present
...
...and then how to rewrite the validates :role, uniqueness: ... statement above to include the localized text?

As mentioned in the comment by Les Nightingill, the correct key is taken, not uniqueness.
And if you choose carefully, you can often avoid messages per-model and just use the same for all models. Here's how I've done it:
#config/locales/en.yml
en:
errors:
format: "%{message}"
header: 'The form entry has errors; please correct the errors below and re-submit.'
messages:
accepted: "The %{attribute} was not accepted; please accept the %{attribute}."
blank: "The provided %{attribute} is blank; please enter a non-blank %{attribute}."
confirmation: "The provided %{attribute} does not match the corresponding entry; please re-check this entry against the original."
empty: "The provided %{attribute} is empty; please enter a non-empty %{attribute}."
equal_to: "The provided %{attribute} is incorrect; please enter exactly %{count}."
even: "The provided %{attribute} is odd; please enter an even %{attribute}."
exclusion: "The provided %{attribute} is reserved; please enter a different %{attribute}."
greater_than: "The provided %{attribute} is too small; please provide a different %{attribute} greater than %{count}."
greater_than_or_equal_to: "The provided %{attribute} is too small; please provide a different %{attribute} greater than or equal to %{count}."
inclusion: "The chosen %{attribute} is not available; please choose an available option." # Rails 4
inclusion_of: "The chosen %{attribute} is not available; please choose an available option." # Rails 5
invalid: "The provided %{attribute} is invalid; please enter a valid %{attribute}."
in_between: "The provided %{attribute} is outside of the accepted range; please enter a different %{attribute} within the range of %{min} to %{max}."
less_than: "The provided %{attribute} is too large; please provide a different %{attribute} less than %{count}."
less_than_or_equal_to: "The provided %{attribute} is too large; please provide a different %{attribute} less than or equal to %{count}."
not_a_number: "The provided %{attribute} is not numeric; please enter a numeric %{attribute}."
odd: "The provided %{attribute} is even; please enter an odd %{attribute}."
record_invalid: "The %{attribute} is invalid. %{errors}"
spoofed_media_type: "The provided %{attribute} is invalid (often due to an incorrect file extension); please provide a valid %{attribute}, including an appropriate file extension."
too_long: "The provided %{attribute} contains more than the %{count} available characters; please shorten the entry."
too_short: "The provided %{attribute} contains fewer than the %{count} required characters; please lengthen the entry."
taken: "The provided %{attribute} is already taken; please enter a different %{attribute}."
wrong_length: "The provided %{attribute} contains the wrong amount of characters; please adjust the entry to exactly %{count} characters."

Related

Custom error message for password presence validation

It seems like this should be straightforward. When signing up new users, I want custom errors for blank user names and passwords. It worked fine for the user name:
validates :name, presence: { message: "Please enter a name." },
length: { maximum: 50,
message: "Please enter a name shorter than 50 characters"}
When the field is blank, it gives the "Please enter a name." error.
I the same thing for the password:
has_secure_password
validates :password, presence: { message: "Please enter a password." },
length: { minimum: 8,
message: "Please choose a password with at least 8 \
characters."}
The minimum length message works fine. But if I submit with an empty password, I get the default "can't be blank" message.
has_secure_password automatically adds some validations for you:
Password must be present on creation
Password length should be less than or equal to 72 characters
Confirmation of password (using a password_confirmation attribute)
To prevent that, declare:
has_secure_password validations: false
And then you can add your own.
has_secure_password validations: false worked at first, but I had a problem when I made the edit user profile page. It assumes the user might not enter a password. So it depends on the validations in has_secure_password, which the answer above disables.
A better way is to edit config/local/en.yml:
en:
activerecord:
attributes:
user:
password: "Password"
errors:
models:
user:
attributes:
password:
blank: "Please enter a password."

Can I specify a default error message format for a single validator across all attributes?

I know you can do this:
# config/locales/en.yml
en:
activerecord:
attributes:
user:
email: "E-mail address"
errors:
models:
user:
attributes:
email:
blank: "is required"
via https://stackoverflow.com/a/2859275/718050
Question 1
Is it possible to specify the message for blank across an entire model, or even sitewide, instead of going into every single attribute?
Question 2
Also, it seems that blank comes from :presence in the model, e.g.
validates :email, :presence => true
So if a :presence => true error translates to blank:, where can I find a list of these translations? How am I supposed to know what :unique => true turns into inside en.yml?
This list is here and here
as you can see you can redefine blank error like this:
en:
errors:
messages:
blank: "can't be blank"

Is Rails 3 missing an error translation?

In my en.yml I have this:
en:
errors:
format: "%{message}"
messages:
blank: "%{attribute} can't be blank"
invalid: "%{attribute} is invalid"
too_short: "%{attribute} is too short"
too_long: "%{attribute} is too long"
wrong_length: "%{attribute} is the wrong length"
taken: "%{attribute}, {value}, is already taken"
And here's my User model so far:
validates_presence_of :username
validates_uniqueness_of :username
validates_length_of :username, :within => 4..15
validates_format_of :username, :with => /^\w+$/i
validates_presence_of :password
validates_length_of :password, :within => 6..20
When I test random data, all error messages work great, except for the validates_uniqueness_of, which returns the default 'has already been taken'
Thank you very much in advance.
shouldn't it be
taken: "%{attribute}, %{value}, is already taken"
with percent sign for value?
I didn't know you could access value, but it makes sense, otherwise that could be username.
I see that taken is the right key, but I still would try without {value} to see if it works.
At last or temporary fix I think you can pass a message in you model validation, something like this should work:
validates_uniqueness_of :username, :mesage => "#{self.username} is already taken"
but of course you loose a lot of benefits.

errors.full_messages: attribute name appears twice

This has been bugging me for a while. This problem occurs with all of my models, but i'll use one of them, Quiz, as an example.
Quiz has the following validations:
validates_presence_of :size, :style
I'm using I18n, and i have the following set in my translations file: (these are just the standard error messages, but i've included them in my en.yml so that it's easy to see the structure, if i want to override them for any particular model)
activerecord:
errors:
messages:
inclusion: "{{attribute}} is not included in the list"
invalid: "{{attribute}} is invalid"
empty: "{{attribute}} can't be empty"
blank: "{{attribute}} can't be blank"
record_invalid: "Validation failed: {{errors}}"
The problem is this: if i make a new quiz, which will fail validation, then look at quiz.errors.full_messages, each error message has the attribute then the full message:
>> quiz = Quiz.create
=> <unsaved quiz object>
>> quiz.errors.full_messages
=> ["Size Size can't be blank", "Style Style can't be blank"]
I don't understand why the message is, for example, "Size Size can't be blank" and not "Size can't be blank"
Any ideas anyone?
There should be also:
en:
errors:
# The default format to use in full error messages.
format: "%{attribute} %{message}"
And your other translations shouldn't include %{attribute} anymore.
To make sure you get all correctly use en.yml from your Rails version,
it is located at: lib/ruby/gems/1.8/gems/activemodel-3.0.3/lib/active_model/locale/en.yml
I just figured this out and thought i'd answer it myself in case anyone else had this problem: i had to amend the activerecord part of my translations file thus:
activerecord:
errors:
full_messages:
format: "{{message}}"
#define standard error messages, which we can overide on per model/per attribute basis further down
messages:
inclusion: "{{attribute}} is not included in the list"
exclusion: "{{attribute}} is reserved"
The problem was that the activerecord.errors.full_messages.format key was set (in vendor/rails/activerecord/lib/active_record/locale/en.yml) to "{{attribute}} {{message}}", and the messages in turn were set to "{{attribute}} can't be blank" for example. So the full_message was coming out as "{{attribute}} {{attribute}} can't be blank". Changing it to be just "{{message}}" fixed this.

Ruby on Rails: controlling the layout of an error message in ActiveRecord

My error messages in Rails look like the following:
"Email Your email is invalid."
Why is the name of the field prefixed within the string itself? It makes the error messages look awfully odd.
Is there anyway to circumvent this behavior so that I can just see "Your email is invalid."
The documentation for generate_full_message might be of use:
The default full_message format for any locale is "{{attribute}} {{message}}". One can specify locale specific default full_message format by storing it as a translation for the key: "activerecord.errors.full_messages.format".
Additionally one can specify a validation specific error message format by storing a translation for: "activerecord.errors.full_messages.[message_key]". E.g. the full_message format for any validation that uses :blank as a message key (such as validates_presence_of) can be stored to: "activerecord.errors.full_messages.blank".
Because the message key used by a validation can be overwritten on the validates_* class macro level one can customize the full_message format for any particular validation:
# app/models/article.rb
class Article < ActiveRecord::Base
validates_presence_of :title, :message => :"title.blank"
end
# config/locales/en.yml
en:
activerecord:
errors:
full_messages:
title:
blank: This title is screwed!
In your case, since you're using the default {{attribute}} {{message}} format, you're getting "Email" for the attribute and "Your email is invalid" as the message. You could change the :message argument to "is not a valid format" and you should get "Email is not a valid format". That's the quick fix. If you want to fully customize it you can use the locale method above.

Resources