Carlos Medeiros

I'm Programmer for Ruby & Rails

How To Add Attribute Name and Value to Validation

08 Jun 2020 » general

Validations?


Validations are an application-level method to ensure consistency on your database by only allowing valid data to be written on it.

Rails chooses to write validations in the Model by default to keep the fat modal, skinny controller approach.

:message

By using the :message option, Rails allows us to give the user a custom error message. :message accepts a string or a proc to define its content. Once the validation is triggered, the message is added to the error collection and possibly sent to the user through a flash message by the controller or simply as an api return.

string

If a simple string is enough to express the error, Rails provides `%{value}, %{attribute} and %{model} to use as a string-interpolation so it is dynamically replaced when validation fails.

  validates :amount, numericality: { message: "%{value} seems to not be a number" }

In the above sample, the value of the atttribute that triggered the validation is added inside the message to the error collection.

Proc

If you need a more robust and flexible error message, it is possible to do so by applying proc. The :message’s proc is given two arguments, the Object being validated and a hash with :modal, :attribute and :value key-value pair. A simple use of a Proc as a message would be:

  validates :email, 
    uniqueness: {
      message: ->(object, data) do
        "The email of value, #{data[:value]} is taken already! Try again #{Time.zone.tomorrow}"
      end
    }

You may be wondering why bother with Proc since we already accomplished the same with string interpolation.
If, by any chahnce, you want to display additional information for some users but not for another, you could accomplish this by putting a conditional inside the Proc:

   validates :email, 
    uniqueness: {
      message: ->(object, data) do
        if object.internal?
          "The email of value, #{data[:value]} is taken already! Try again #{Time.zone.tomorrow}"
        else
          "You may not need to do this"
        end
      end
    }

Exercise Time

This one is easy, write a simple validation for your mode. Try to print the value of the attribute that you are trying to validate by using string interpolation.
Do the same by using Proc, but now add a debugger using byebug so you can inspect the values of object and data arguments of your Proc.


Happy Coding!