Custom ActiveRecord Validator
Active Record validation is one of the impartial magic in Rails. These validations are used to ensure only valid data are forwarded to the database. Validations are usually placed on the model that makes it easily testable and maintainable. Here is an example of validation that validates the field as numerical.
validates :age, numericality: { only_integer: true }ActiveRecord validators are really easy and simple to understand. Even though Rails provides the utmost validations, sometimes we need to have our own validator based on our business logic and the application-specific validations. Let’s take an example of an application where the business is specific to Nepal and the user needs a Nepalese phone number. The business requirement is that the phone number must be valid only if it matches the criteria for a Nepalese phone number. This requirement can be fulfilled by adding the custom validation in the model defining a method to validate the input as follows:
validate :nepal_phone_number?def nepal_phone_number?
return if phone_number =~ /^(?:\+?977)\d{10}\z/
errors.add(:phone_number, “must be a valid Nepalese phone number”)
end
The above method adds an error and prevents saving data in the database if the number does not satisfy the regex for the Nepalese phone number. This is perfect but sometimes application needs the same validations in multiple places. For eg, the phone number validations might be required in the client number, a contact person number, and so on. We can definitely keep the method in the module and include it in each model as required if the field name is the same or with some tweaks for the different field names. Here comes the role of Active Record Custom Validator.
Get Suman Awal’s stories in your inbox
Join Medium for free to get updates from this writer.
We can create a custom validator file inside the validators folder as follows:
# api/validators/nepalese_phone_number_validator.rbclass NepalesePhoneNumberValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return unless value.present? unless value =~ /^(?:\+?977)\d{10}\z/
record.errors.add(attribute, “must be a valid Nepalese phone number”)
end
end
This validator can be easily integrated into any field that requires to be the Nepalese phone number.
validates :phone_number, nepalese_phone_number: trueThis approach really helps to keep the code clean and maintainable in the large app where we need to validate different fields in different ways based on the business need. Happy Coding!!





