Thursday, February 21, 2013

Experimenting Rails Validation Helpers

(This experiment is performed using Ruby version 1.9.3 and Rails version 3.0.9)

This post is to experiment the Rails validation helpers. Rails validation helpers are just shortcut of some very common validations. For example, a username attribute of the User class must be no longer than 16 characters. How to use these validation helper is very straightforward: just pass in the attribute on which you want to validate and set up the configuration options. Here is how I experiment them. I create a User class, which has attributes username, firstname, lastname, age, birthday, language, balance, password and two instance variables terms and password_confirmation. The required validation on these attributes and instance variables are upon each save
- term must be true
- password and password_confirmation must be the same
- firstname and lastname must not contain spaces
- age must be greater than 17
- birthday format must be in the form "xx/xx/xx"
- language must be either "English" or "Chinese"
- username must be no longer than 16 characters
- balance must be greater than 0.0
- username must be unique

To achieve the validations above, I add the following validation helpers in my User class.
class User < ActiveRecord::Base
  validates_acceptance_of :terms, 
                          :message => 'Please accept the terms to proceed'  validates_confirmation_of :password, :password_confirmation
  validates_each :firstname, :lastname do |model, attr, value|
    if value.include?(' ')
      model.errors.add(attr, "User #{model.id} has a #{attr} which contains spaces")    end
  end
  validates_exclusion_of :age, 
                         :in => 1..17, 
                         :message => 'All users must be 18 year old or higher'  validates_format_of :birthday, 
                      :with => /^[0-9]{2}\/[0-9]{2}\/[0-9]{2}$/
  validates_inclusion_of :language,
                         :in => ['English', 'Chinese'], 
                         :message => 'should be either English or Chinese'  validates_length_of :username, 
                      :maximum => 16, 
                      :message => 'username too long'
  validates_numericality_of :balance, 
                            :greater_than => 0.0
  validates_presence_of :term, :password_confirmation
  validates_uniqueness_of :username
end

All these validations will be invoked when you call valid? or save! on any object of the User class. The error messages will be saved to a hash structure called errors of that object.

Note that validates_acceptance_of and validates_confirmation_of can be performed only if terms and password_confirmation are not nil, and by default only on save. So make sure terms and password_confirmation are not nil using validates_presence_of.

Another thing that is very important is validates_uniqueness_of doesn't really guarantee the unique value of a column. Use database-level constraints instead.

No comments:

Post a Comment