I'm building an authentication system in Rails5 and I have a User for which I want to check the uniqueness and correct format for the email field. I've seen that both errors throw the same exception, ActiveRecord::RecordInvalid and I'd like to know how could I manage both cases in a good and elegant way.
This would be the important part of my model User:
validates_format_of :email, with: URI::MailTo::EMAIL_REGEXP
validates_presence_of :email
validates_uniqueness_of :email
And this would be the controller:
begin
user.save!
render status: :created, json: { msg: 'User was created.' }
rescue ActiveRecord::RecordInvalid => err
render status: conflict, json: { msg: err }
end
What I'd like to do is to differentiate between Uniqueness error (to return a 409) and format error (to return a 400).
I'll appreciate any comment or help about how to do this check in the better way.
Catching the ActiveRecord::RecordInvalid
exception is not the best way to handle this case. Instead, I would suggest to run validation explicitly and checking the errors
object.
Check Rails API documentation for ActiveModel::Validations
(https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-errors) and ActiveModel::Errors
(https://api.rubyonrails.org/classes/ActiveModel/Errors.html).
After running user.valid?
, you can investigate user.errors
object to detect exact kind of validation error. Then you can reply with different response codes as you want:
if !user.valid?
if user.errors[:email] == [" ... uniqueness error ..."]
# return 409
elsif user.errors[:email] == [" ... format error ..."]
# return 400
else
# ...
end
else
user.save!
# ...
end