January 23, 2021
Hot Topics:

Advanced Active Record Validations with Rails

  • By Jason Gilmore
  • Send Email »
  • More Articles »

In the first installment of this two-part series, you examined the data validation features available within the Rails framework's Active Record implementation. Among other tasks, you learned how to use built-in methods such as validates_presence_of() and validates_length_of() to place constraints on user-supplied data and notify the user if these constraints are violated. Doing so goes a long way towards ensuring not only the validity of your data, but also helps to negate attempts to surreptitiously insert malicious data into the application.

In this second installment, I'll introduce you to Active Record's validation callbacks. These callbacks allow you to perform even more powerful operations both prior to and following validation. As a basis for the examples found in this article, you'll continue using the Question model created in the previous article.

I'll close the article with an answer to a reader's question regarding how to remove attribute names from the beginning of custom validation error messages.

To refresh your memory, the corresponding questions MySQL table schema looks like this:

|Field         |Type        |Null|Key|Default|Extra         |
|id            |int(11)     |NO  |PRI|NULL   |auto_increment|
|name          |varchar(255)|NO  |   |       |              |
|email         |varchar(255)|NO  |   |       |              |
|phone         |varchar(255)|NO  |   |       |              |
|contact_method|varchar(255)|NO  |   |       |              |
|message       |text        |NO  |   |       |              |

Active Record Validation Callbacks

Active Record comes equipped with six validation-specific callbacks that you can use to perform a wide variety of cleanup operations. These callbacks allow you to execute various procedures at predefined points as specified by the callback. I'll define each of the callbacks here, and then you'll work through several practical examples illustrating their use:

Callback When It Executes
after_validation() After all validation procedures are complete
after_validation_on_create() After validation of new objects
after_validation_on_update() After validation of existing objects being updated
before_validation() Before the object is validated
before_validation_on_create() Before validation of new objects
before_validation_on_update() Before validation of existing objects being updated

Although I won't use them within any examples, a number of other useful callbacks are also available, some of which include:

Callback When It Executes
before_create() Before the object is added to the database
before_destroy() Before an object is destroyed
before_save() Before an object is saved to the database, either by way of creation or an update
before_update() Before an object is modified in the database

Be sure to weigh the meaning of each callback carefully, because of the subtle differences. For instance, if you're only interested in executing a certain procedure before validation of new database objects, you should use before_validation_on_create() instead of before_validation(), because the latter will trigger prior to validation for both new objects and for those being modified.

Sanitizing a Phone Number

You might recall that, at the conclusion of last week's article, I challenged you to use validates_format_of() to validate a phone number. The difficulty of doing so lies within accounting for a wide variety of phone number formats, (NNN) NNN-NNNN, NNN-NNN-NNNN, and NNN.NNN.NNNN among them. Sure, you could simply enforce a particular format and display an error message if the user doesn't follow it, or divide the phone number input field into three separate input fields, but the most user-friendly approach would be to allow the user to use whatever format he pleases and then strip out any non-numerical characters. You can strip out these characters using the gsub() method. To try it out, fire up the Rails console and execute the following command:

>> "(614) 999-9999".gsub(/[^0-9]/, "")
=> "6149999999"

In this case, the gsub() method replaces any character not found in the range 0-9 with nothing (essentially removing them), and returning what remains. You can use this approach to deal with any of the aforementioned phone number formats. Logically, you'll still want to verify that the user provided a total of ten digits, so you can strip these characters before validation by using before_validation_on_create():

class Question < ActiveRecord::Base

   def before_validation_on_create
      self.phone = phone.gsub(/[^0-9]/, "")


Of course, because this happens before validation you're free to institute the typical validations required of a phone number, such as whether it exists in the first place (presuming you've decided to make this a mandatory part of user input), and whether it consists of 10 digits:

class Question < ActiveRecord::Base

   def before_validation_on_create
      self.phone = phone.gsub(/[^0-9]/, "")

   validates_presence_of :phone, "can't be blank!"
   validates_length_of :phone, :is=>10,
      "must consist of 10 digits!"


Page 1 of 2

This article was originally published on November 26, 2007

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date