method

validates_format_of

validates_format_of(*attr_names)
public

Validates whether the value of the specified attribute is of the correct form by matching it against the regular expression provided.

  class Person < ActiveRecord::Base
    validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create
  end

Note: use \A and \Z to match the start and end of the string, ^ and $ match the start/end of a line.

A regular expression must be provided or else an exception will be raised.

Configuration options:

  • :message - A custom error message (default is: "is invalid")
  • :allow_nil - If set to true, skips this validation if the attribute is nil (default is: false)
  • :allow_blank - If set to true, skips this validation if the attribute is blank (default is: false)
  • :with - The regular expression used to validate the format with (note: must be supplied!)
  • :on - Specifies when this validation is active (default is :save, other options :create, :update)
  • :if - Specifies a method, proc or string to call to determine if the validation should occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.
  • :unless - Specifies a method, proc or string to call to determine if the validation should not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The method, proc or string should return or evaluate to a true or false value.

6Notes

Using validates_format_of to validate URIs

Olly · Aug 8, 200818 thanks

You can use the validates_format_of with the regular expression in the URI library ensure valid URIs.

==== Example require 'uri'

class Feed < ActiveRecord::Base
validates_format_of :uri, :with => URI.regexp
end

RE: Using validates_format_of to validate URIs

i_am_cam · Aug 11, 200810 thanks

Further to Olly's note below, you can also specify the protocol to further limit the valid uri's, else things like 'ftp ://someurl.com' (there's only a space in there to get it to display on here) would be valid.

validates_format_of :uri, :with => URI.regexp(['http'])

Take care when writing regex

Oleg · Apr 6, 20093 thanks

When you want to validate a field for a continuous string you'd probably write something like this (if it's really early in the morning and you didn't have your coffee yet):

validates_format_of :something => /\\w/

At the first sight it looks like it's working because something = "blahblahblah" is valid. However, so is this: something = "blah meh 55". It's just that your regex matched a substring of the value and not the whole thing. The proper regex you're looking for is actually:

validates_format_of :something => /^\\w$/

Re: Taking care when writing regex

svoop · Nov 11, 20092 thanks

Oleg's example from above contains an error and a pitfall:

validates_format_of :something => /^\\w$/

The string "blahblahblah" doesn't pass this validation. What Oleg ment is rather a continuous string of at least one alphanumeric character:

validates_format_of :something => /^\\w+$/

However, that's no good neither because it contains a well hidden trap in case you are validating content from a textarea.

Ruby (both 1.8 and 1.9) always matches ^ and $ against the beginning and ending of lines and not the entire string. Thus "First line
Second line" will pass the above validation although it's clearly not a continuous string.

You should use \A (replacement for ^) and \z (replacement for $) instead as their scope is the entire string:

validates_format_of :something => /\\A\\w+\\z/

(A side note for those with a Perl background: Please note that the "s" modifier has a different meaning in Ruby and won't do the trick here.)

No numbers or symbols

ncancelliere · Oct 16, 20091 thank

"Kyle", "Дети", "Niños", "Quan-lu", "た ち"

validates_format_of :first_name, :with => /^([^\\d\\W]|[-])*$/

note: the example format regex is too lenient

ColinDKelley · Feb 23, 2010

The example regex for RFC 2822 email is too lenient. Sure it's just an example, but it wound up in our code and we just had to fix it to match the RFC.

The regex as given allows any non-@ non-whitespace characters. But the RFC only allows these characters in mailbox names

alpha digit - ! \\ # $ % & ' * + \\ / = ? ^ _ ` { | } ~ ] +

and . is only allowed between atoms of 1 or more of the above.

Here's the corrected regex:

:with => /\\A([-a-z0-9!\\#$%&'*+\\/=?^_`{|}~]+\\.)*[-a-z0-9!\\#$%&'*+\\/=?^_`{|}~]+@((?:[-a-z0-9]+\\.)+[a-z]{2,})\\Z/i