Recently I was applying some validations to models on a Rails application I’m currently working on when I found myself in a bit of a double pickle. I had a need to get rid of an ActiveModel error message that was being generated and add one that wasn’t. How do you do either of those? Let me tell you how you can do both.
In Rails, when you try saving an object to a database or execute the
.valid? method on it, if any model validations fail, error messages are written to an ActiveModel errors hash. This hash can be accessed by executing
.errors.messages on the object. So let’s say you have a
@user object you execute
@user.valid? on, after doing so, you can execute
@user.errors.messages to check for any error messages. The resulting hash will look something like the following:
1 2 3 4 5 6
This hash comes in handy to display the error messages to the user. Rails makes it even easier with the
.full_messages method. For the errors hash above,
@user.errors.full_messages results in
1 2 3 4 5 6
Iterating through this array and printing the error messages is a snap. But …
What if you don’t want to print one or more of these error messages? For example, “Password digest can’t be blank”. That message will very well leave many a user scratching their head. Let’s get rid of it from the hash.
@user.errors.delete(:password_digest) will do the trick. You can use
.errors.delete(:key) to delete any of the messages in the errors hash.
1 2 3 4 5
The error messages that are automatically generated result from failed validations on model attributes of the object in question. But what about validations you perform on any associations or any non-standard validations? If any of those validations fail and you want a message included in the ActiveModel errors hash, you have to add it in yourself.
In my situation, I performed a validation on a ‘roles’ association with my User model. Since the validation was not on an attribute of my
User model, if the validation failed an error message would not be automatically generated and added to the errors hash. So after a little research I wound up using
@user.errors[:base] << "error message". This added my message to the hash and made it available in the
@user.errors.full_messages array. That easy.
And, should you want to, you can also add additional messages associated with specific model attributes in the same way. For example, if I performed some validation checking that the name entered is all lower-case, on failure I could execute
@user.errors[:name] << "must be all lower-case". The resulting messages array winds up looking as follows:
1 2 3 4 5 6 7