Module ActiveRecord::Validations::ClassMethods
In: vendor/activerecord/lib/active_record/validations.rb

All of the following validations are defined in the class scope of the model that you’re interested in validating. They offer a more declarative way of specifying when the model is valid and when it is not. It is recommended to use these over the low-level calls to validate and validate_on_create when possible.

Methods

Constants

DEFAULT_VALIDATION_OPTIONS = { :on => :save, :allow_nil => false, :message => nil
DEFAULT_SIZE_VALIDATION_OPTIONS = DEFAULT_VALIDATION_OPTIONS.merge( :too_long => ActiveRecord::Errors.default_error_messages[:too_long], :too_short => ActiveRecord::Errors.default_error_messages[:too_short], :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length]
ALL_RANGE_OPTIONS = [ :is, :within, :in, :minimum, :maximum ].freeze

Public Instance methods

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 211
211:       def validate(*methods, &block)
212:         methods << block if block_given?
213:         write_inheritable_set(:validate, methods)
214:       end

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 216
216:       def validate_on_create(*methods, &block)
217:         methods << block if block_given?
218:         write_inheritable_set(:validate_on_create, methods)
219:       end

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 221
221:       def validate_on_update(*methods, &block)
222:         methods << block if block_given?
223:         write_inheritable_set(:validate_on_update, methods)
224:       end

Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:

  class Person < ActiveRecord::Base
    validates_acceptance_of :terms_of_service
    validates_acceptance_of :eula, :message => "must be abided"
  end

The terms_of_service attribute is entirely virtual. No database column is needed. This check is performed only if terms_of_service is not nil and by default on save.

Configuration options:

  • message - A custom error message (default is: "can’t be empty")
  • on - Specifies when this validation is active (default is :save, other options :create, :update)

NOTE: The agreement is considered valid if it’s set to the string "1". This makes it easy to relate it to an HTML checkbox.

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 296
296:       def validates_acceptance_of(*attr_names)
297:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save }
298:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
299:         configuration[:message].gsub!(/\"/, '\\\\\"')
300: 
301:         for attr_name in attr_names
302:           attr_accessor(attr_name)
303:           class_eval(%(#{validation_method(configuration[:on])} %{errors.add('#{attr_name}', "#{configuration[:message]}") unless #{attr_name}.nil? or #{attr_name} == "1"}))
304:         end
305:       end

Validates whether the associated object or objects are all themselves valid. Works with any kind of association.

  class Book < ActiveRecord::Base
    has_many :pages
    belongs_to :library

    validates_associated :pages, :library
  end

Warning: If, after the above definition, you then wrote:

  class Page < ActiveRecord::Base
    belongs_to :book

    validates_associated :book
  end

this would specify a circular dependency and cause infinite recursion. The Rails team recommends against this practice.

Configuration options:

  • on Specifies when this validation is active (default is :save, other options :create, :update)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 504
504:       def validates_associated(*attr_names)
505:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save }
506:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
507:         configuration[:message].gsub!(/\"/, '\\\\\"')
508:         
509:         for attr_name in attr_names
510:           class_eval(%(#{validation_method(configuration[:on])} %{
511:             errors.add("#{attr_name}", "#{configuration[:message]}") unless
512:               (#{attr_name}.is_a?(Array) ? #{attr_name} : [#{attr_name}]).inject(true){ |memo, record| (record.nil? or record.valid?) and memo }
513:           }))
514:         end
515:       end

Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:

  Model:
    class Person < ActiveRecord::Base
      validates_confirmation_of :user_name, :password
      validates_confirmation_of :email_address, :message => "should match confirmation"
    end

  View:
    <%= password_field "person", "password" %>
    <%= password_field "person", "password_confirmation" %>

The person has to already have a password attribute (a column in the people table), but the password_confirmation is virtual. It exists only as an in-memory variable for validating the password. This check is performed only if password_confirmation is not nil and by default on save.

Configuration options:

  • message - A custom error message (default is: "doesn’t match confirmation")
  • on - Specifies when this validation is active (default is :save, other options :create, :update)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 270
270:       def validates_confirmation_of(*attr_names)
271:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save }
272:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
273:         configuration[:message].gsub!(/\"/, '\\\\\"')
274: 
275:         for attr_name in attr_names
276:           attr_accessor "#{attr_name}_confirmation"
277:           class_eval(%(#{validation_method(configuration[:on])} %{errors.add('#{attr_name}', "#{configuration[:message]}") unless #{attr_name}_confirmation.nil? or #{attr_name} == #{attr_name}_confirmation}))
278:         end
279:       end

Validates each attribute against a block.

  class Person < ActiveRecord::Base
    validates_each :first_name, :last_name do |record, attr|
      record.errors.add attr, 'starts with z.' if attr[0] == ?z
    end
  end

Options:

  • on - Specifies when this validation is active (default is :save, other options :create, :update)
  • allow_nil - Skip validation if attribute is nil.

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 237
237:       def validates_each(*attrs)
238:         options = attrs.last.is_a?(Hash) ? attrs.pop.symbolize_keys : {}
239:         attrs = attrs.flatten
240: 
241:         # Declare the validation.
242:         send(validation_method(options[:on] || :save)) do |record|
243:           attrs.each do |attr|
244:             value = record.send(attr)
245:             next if value.nil? && options[:allow_nil]
246:             yield record, attr, value
247:           end
248:         end
249:       end

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 => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/, :on => :create
  end

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

Configuration options:

  • message - A custom error message (default is: "is invalid")
  • 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)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 441
441:       def validates_format_of(*attr_names)
442:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save, :with => nil }
443:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
444:         configuration[:message].gsub!(/\"/, '\\\\\"')
445: 
446:         raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp)
447: 
448:         for attr_name in attr_names 
449:           class_eval(%(#{validation_method(configuration[:on])} %{errors.add("#{attr_name}", "#{configuration[:message]}") unless #{attr_name} and #{attr_name}.to_s.match(/#{Regexp.quote(configuration[:with].source)}/)}))
450:         end
451:       end

Validates whether the value of the specified attribute is available in a particular enumerable object.

  class Person < ActiveRecord::Base
    validates_inclusion_of :gender, :in=>%w( m f ), :message=>"woah! what are you then!??!!"
    validates_inclusion_of :age, :in=>0..99
  end

Configuration options:

  • in - An enumerable object of available items
  • message - Specifies a customer error message (default is: "is not included in the list")
  • allow_nil - If set to true, skips this validation if the attribute is null (default is: false)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 464
464:       def validates_inclusion_of(*attr_names)
465:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:inclusion], :on => :save }
466:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
467:         configuration[:message].gsub!(/\"/, '\\\\\"')
468: 
469:         enum = configuration[:in] || configuration[:within]
470:         allow_nil = configuration[:allow_nil]
471: 
472:         raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?")
473: 
474:         for attr_name in attr_names
475:           if allow_nil
476:             class_eval(%(#{validation_method(configuration[:on])} %{errors.add("#{attr_name}", "#{configuration[:message]}") unless #{attr_name}.nil? or (#{enum.inspect}).include?(#{attr_name}) }))
477:           else
478:             class_eval(%(#{validation_method(configuration[:on])} %{errors.add("#{attr_name}", "#{configuration[:message]}") unless (#{enum.inspect}).include?(#{attr_name}) }))
479:           end
480:         end
481:       end

Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time:

  class Person < ActiveRecord::Base
    validates_length_of :first_name, :maximum=>30
    validates_length_of :last_name, :maximum=>30, :message=>"less than %d if you don't mind"
    validates_length_of :fax, :in => 7..32, :allow_nil => true
    validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name"
    validates_length_of :fav_bra_size, :minimum=>1, :too_short=>"please enter at least %d character"
    validates_length_of :smurf_leader, :is=>4, :message=>"papa is spelled with %d characters... don't play me."
  end

Configuration options:

  • minimum - The minimum size of the attribute
  • maximum - The maximum size of the attribute
  • is - The exact size of the attribute
  • within - A range specifying the minimum and maximum size of the attribute
  • in - A synonym(or alias) for :within
  • allow_nil - Attribute may be nil; skip validation.
  • too_long - The error message if the attribute goes over the maximum (default is: "is too long (max is %d characters)")
  • too_short - The error message if the attribute goes under the minimum (default is: "is too short (min is %d characters)")
  • wrong_length - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %d characters)")
  • message - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message
  • on - Specifies when this validation is active (default is :save, other options :create, :update)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 346
346:       def validates_length_of(*attrs)
347:         # Merge given options with defaults.
348:         options = DEFAULT_SIZE_VALIDATION_OPTIONS.dup
349:         options.update(attrs.pop.symbolize_keys) if attrs.last.is_a?(Hash)
350: 
351:         # Ensure that one and only one range option is specified.
352:         range_options = ALL_RANGE_OPTIONS & options.keys
353:         case range_options.size
354:         when 0
355:           raise ArgumentError, 'Range unspecified.  Specify the :within, :maximum, :minimum, or :is option.'
356:         when 1
357:           # Valid number of options; do nothing.
358:         else
359:           raise ArgumentError, 'Too many range options specified.  Choose only one.'
360:         end
361: 
362:         # Get range option and value.
363:         option = range_options.first
364:         option_value = options[range_options.first]
365: 
366:         # Declare different validations per option.
367:         case range_options.first
368:         when :within, :in
369:           raise ArgumentError, ':within must be a Range' unless option_value.is_a?(Range)
370:           validates_each(attrs, options) do |record, attr|
371:             next if record.send(attr).nil? and options[:allow_nil]
372:             record.errors.add_on_boundary_breaking(attr, option_value, options[:too_long], options[:too_short])
373:           end
374:         when :is
375:           raise ArgumentError, ':is must be a nonnegative Integer' unless option_value.is_a?(Integer) and option_value >= 0
376:           message = options[:message] || options[:wrong_length]
377:           message = (message % option_value) rescue message
378:           validates_each(attrs, options) do |record, attr, value|
379:             record.errors.add(attr, message) if value.nil? or value.size != option_value
380:           end
381:         when :minimum
382:           raise ArgumentError, ':minimum must be a nonnegative Integer' unless option_value.is_a?(Integer) and option_value >= 0
383:           message = options[:message] || options[:too_short]
384:           message = (message % option_value) rescue message
385:           validates_each(attrs, options) do |record, attr, value|
386:             record.errors.add(attr, message) if value.nil? or value.size < option_value
387:           end
388:         when :maximum
389:           raise ArgumentError, ':maximum must be a nonnegative Integer' unless option_value.is_a?(Integer) and option_value >= 0
390:           message = options[:message] || options[:too_long]
391:           message = (message % option_value) rescue message
392:           validates_each(attrs, options) do |record, attr, value|
393:             record.errors.add(attr, message) if value.nil? or value.size > option_value
394:           end
395:         end
396:       end

Validates whether the value of the specified attribute is numeric by trying to convert it to a float with Kernel.Float (if integer is false) or applying it to the regular expression /^[+\-]?\d+$/ (if integer is set to true).

  class Person < ActiveRecord::Base
    validates_numericality_of :value, :on => :create
  end

Configuration options:

  • message - A custom error message (default is: "is not a number")
  • on Specifies when this validation is active (default is :save, other options :create, :update)
  • only_integer Specifies whether the value has to be an integer, e.g. an integral value (default is false)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 529
529:       def validates_numericality_of(*attr_names)
530:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:not_a_number], :on => :save,
531:                            :integer => false }
532:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
533: 
534:         for attr_name in attr_names
535:           if configuration[:only_integer]
536:             # we have to use a regexp here, because Kernel.Integer accepts nil and "0xdeadbeef", but does not
537:             # accept "099" and String#to_i accepts everything. The string containing the regexp is evaluated twice
538:             # so we have to escape everything properly
539:             class_eval(%(#{validation_method(configuration[:on])} %{
540:                 errors.add("#{attr_name}", "#{configuration[:message]}") unless #{attr_name}_before_type_cast.to_s =~ /^[\\\\+\\\\-]?\\\\d+$/
541:             }))          
542:           else
543:             class_eval(%(#{validation_method(configuration[:on])} %{
544:                 begin
545:                   Kernel.Float(#{attr_name}_before_type_cast)
546:                 rescue ArgumentError, TypeError
547:                   errors.add("#{attr_name}", "#{configuration[:message]}")
548:                 end
549:             }))
550:           end
551:         end
552:       end

Validates that the specified attributes are neither nil nor empty. Happens by default on save.

Configuration options:

  • message - A custom error message (default is: "has already been taken")
  • on - Specifies when this validation is active (default is :save, other options :create, :update)

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 312
312:       def validates_presence_of(*attr_names)
313:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:empty], :on => :save }
314:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
315:         configuration[:message].gsub!(/\"/, '\\\\\"')
316: 
317:         for attr_name in attr_names
318:           class_eval(%(#{validation_method(configuration[:on])} %{errors.add_on_empty('#{attr_name}', "#{configuration[:message]}")}))
319:         end
320:       end
validates_size_of(*attrs)

Validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user can be named "davidhh".

  class Person < ActiveRecord::Base
    validates_uniqueness_of :user_name, :scope => "account_id"
  end

When the record is created, a check is performed to make sure that no record exist in the database with the given value for the specified attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself.

Configuration options:

  • message - Specifies a custom error message (default is: "has already been taken")
  • scope - Ensures that the uniqueness is restricted to a condition of "scope = record.scope"

[Source]

     # File vendor/activerecord/lib/active_record/validations.rb, line 414
414:       def validates_uniqueness_of(*attr_names)
415:         configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] }
416:         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
417:         configuration[:message].gsub!(/\"/, '\\\\\"')
418: 
419:         for attr_name in attr_names
420:           if scope = configuration[:scope]
421:             class_eval(%(validate %{errors.add('#{attr_name}', "#{configuration[:message]}") if self.class.find_first(new_record? ? ['#{attr_name} = ? AND #{scope} = ?', #{attr_name}, #{scope}] : ["#{attr_name} = ? AND \\\#{self.class.primary_key} <> ? AND #{scope} = ?", #{attr_name}, id, #{scope}])}))
422:           else
423:             class_eval(%(validate %{errors.add('#{attr_name}', "#{configuration[:message]}") if self.class.find_first(new_record? ? ['#{attr_name} = ?', #{attr_name}] : ["#{attr_name} = ? AND \\\#{self.class.primary_key} <> ?", #{attr_name}, id])}))
424:           end
425:         end
426:       end

[Validate]