Rails Model Validators

When developing a Ruby on Rails web application it is a good idea to use ActiveRecord validators to insure the state of a record before posting it to the database. To flush out this example I present the following model:

class User < ActiveRecord::Base
  validates_uniqueness_of :username
  validates_presence_of :username, :password, :email
  validates_size_of :username, :password, :within => 5..15
  validates_format_of :email,
    :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
  validates_format_of :username, :with => /^\w+$/i,
    :message => "can only contain letters and numbers."
  validates_confirmation_of :password
  validates_inclusion_of :gender, :in => %w(male female)
  validates_acceptance_of :eula
end

This class models a user in a rails application. The application would normally have a user registration page and a login page. These user validations are checked when trying to save the model into the database but most of them support a :on options that accepts either the :save, :create, or :update values.

Let me now walk through each validation. The validates_uniqueness_of method ensures that the named attribute is unique in the system. In this case, when the record is being saved the system will check against the database to ensure that the username is unique. As mentioned above, this method supports the :on option. This validator also supports a :scope option that limits the scope of uniqueness, meaning that the combination of the values of the named attribute and those listed in the :scope option must be unique.

The validates_presence_of method insures that the list of attributes are not nil, empty, or blank. In this example the username and password attributes require a non empty string value. This validator also supports the :on option.

The validates_size_of method allows you to define the minimum, or maximum, or exact character size of a attribute. In the example above, I used the within range to indicate both the minimum and maximum size of a string.

The validates_format_of method allows you to validate the value of an attribute against a regular expression. The first example of the validates_format_of above is taken straight from the rails documentation and validates that the email attribute actually looks like an email address. The second validate_format_of method ensures that only alphanumeric characters are used for a username.

The validates_confirmation_of method is used to validate that the password typed in is the one the user intended. To confirm the password entered by a user you need to define two input fields in the form to check that they both match. The system will automatically check that the two password match when the user record is saved. Again, this validator supports the :on option. In my registration page I have a form with the following two password fields.

<label for="user_password">Password</label>
<%= password_field 'user', 'pass' %>
<label for="check_password">Confirm Password</label>
<%= password_field 'user', 'pass_confirmation' %>

The validates_inclusion_of method validates that the value of named attribute is in the list specified by the :in option. In this example, the gender of the user needs to be either male or female. You can also specify a range instead of a list. ActiveRecord also supports a validates_exclusion_of method that validates that the value of a named attribute is not within the range or list provided in the :in option.

The validates_acceptance_of method validates that the user accepted some sort of end user license agreement, term or service, or memorandum of understanding via a checkbox in a from. The validates_acceptance_of validator works only when you define a checkbox in the form. This means that in the registration page you can add the acceptance checkbox so that the user must accept the EULA but you can leave out the acceptance checkbox in the user update page. In this example, only when the form has the eula checkbox does this validator takes effect. For this example here is how you define the acceptance checkbox in your user registration form:

<%= check_box :user, :eula %>

To create the checkbox I am using symbols instead of strings, either one works.

There are a few other rails validators that I did not cover here such as validates_associated which is used to validate ActiveRecord associations, validates_numericality_of which can be used to validate if a form value is a number, and validates_each which allows you to define you own validation code blocks.

Technorati Tags: , , , , , ,

Enjoy. Share. Be Happy.
  • Twitter
  • Facebook
  • StumbleUpon
  • del.icio.us
  • Tumblr
  • Google Bookmarks
  • FriendFeed
  • Yahoo! Buzz
  • Reddit
  • Digg
  • HackerNews
  • Suggest to Techmeme via Twitter
  • LinkedIn
  • Ping.fm
  • Identi.ca
  • Mixx
  • Furl

Related posts:

  1. Raising Model Errors In Rails
  2. Flex On Rails
  3. Riff Rails Plugin
  4. ActiveRecord: Ruby on Rails Optional
  5. Rails Acts As Authenticated Plugin

This entry was posted in Ruby, TechKnow. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

10 Comments

  1. Posted February 23, 2007 at 12:15 pm | Permalink

    Wondering if this line ever actually worked:

    validates_format_of :username, :with => /^w+$/i,
      :message => "can only contain letters and numbers."
    

    I think the ‘w’ needs escaped in order to represent any letter and number versus simply the character ‘w’. So the regex would look like: /^\w+$/i

  2. Posted February 24, 2007 at 11:20 am | Permalink

    @bjhess – Thanks for catching the typo. You are right, it doesn’t work without the backward slash. But the typo is caused by WordPress itself. It seems that I do in fact have a slash in the post when I edit it, but when the post is display WP removes that slash. Maybe i’ll escape the back slash itself with an HTML entity.

  3. Posted February 24, 2007 at 11:34 am | Permalink

    @bjhess – Yeah, replacing the backslash (\) with a &#092; entity fixed the problem. Unfortunately I have had to do this type of ‘fix’ one to many times with WP. But once again, thanks for the heads up on the typo.

  4. Posted February 25, 2007 at 9:44 am | Permalink

    Wordpress, you say? Try this code auto escape plugin.

  5. Posted April 23, 2007 at 7:44 am | Permalink

    Validates email doesn’t seem to work with international extensions like user@domain.com.au

  6. linoj
    Posted October 9, 2007 at 12:13 am | Permalink

    fyi, found this for emails, it’s working for me so far
    http://code.dunae.ca/validates_email_format_of

  7. naushad pasha
    Posted May 2, 2008 at 5:30 am | Permalink

    Good Knowledge of validators – thanks

  8. Terra
    Posted October 7, 2008 at 10:09 am | Permalink

    How can we restict validation of models only in selected forms, say I need validation of model Address in one form but want to ignore in another form ?

    Would appreciate your reply

    Sira

  9. Posted January 5, 2009 at 8:38 am | Permalink

    Thanks. I could not even find these on the Rails guide.

  10. Gonzotim
    Posted February 5, 2009 at 9:15 am | Permalink

    Brilliant! I’m a rubynoob, and it’s pages like this that make it possible. Rails guide not so fun.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*