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.
- validate
- validate_on_create
- validate_on_update
- validates_acceptance_of
- validates_associated
- validates_confirmation_of
- validates_each
- validates_format_of
- validates_inclusion_of
- validates_length_of
- validates_numericality_of
- validates_presence_of
- validates_size_of
- validates_uniqueness_of
| 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 |
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 214
214: def validate(*methods, &block)
215: methods << block if block_given?
216: write_inheritable_set(:validate, methods)
217: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 219
219: def validate_on_create(*methods, &block)
220: methods << block if block_given?
221: write_inheritable_set(:validate_on_create, methods)
222: end
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 224
224: def validate_on_update(*methods, &block)
225: methods << block if block_given?
226: write_inheritable_set(:validate_on_update, methods)
227: 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)
- accept - Specifies value that is considered accepted. The default value is a string "1", which
makes it easy to relate to an HTML checkbox.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 301
301: def validates_acceptance_of(*attr_names)
302: configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" }
303: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
304:
305: attr_accessor *attr_names
306:
307: validates_each(attr_names,configuration) do |record, attr_name, value|
308: record.errors.add(attr_name, configuration[:message]) unless value == configuration[:accept]
309: end
310: 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)
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 494
494: def validates_associated(*attr_names)
495: configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save }
496: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
497:
498: validates_each(attr_names, configuration) do |record, attr_name, value|
499: record.errors.add(attr_name, configuration[:message]) unless
500: (value.is_a?(Array) ? value : [value]).inject(true) { |memo, r| (r.nil? or r.valid?) and memo }
501: end
502: 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)
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 273
273: def validates_confirmation_of(*attr_names)
274: configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save }
275: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
276:
277: attr_accessor *(attr_names.map { |n| "#{n}_confirmation" })
278:
279: validates_each(attr_names, configuration) do |record, attr_name, value|
280: record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation")
281: end
282: 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.
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 240
240: def validates_each(*attrs)
241: options = attrs.last.is_a?(Hash) ? attrs.pop.symbolize_keys : {}
242: attrs = attrs.flatten
243:
244: # Declare the validation.
245: send(validation_method(options[:on] || :save)) do |record|
246: attrs.each do |attr|
247: value = record.send(attr)
248: next if value.nil? && options[:allow_nil]
249: yield record, attr, value
250: end
251: end
252: 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)
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 438
438: def validates_format_of(*attr_names)
439: configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save, :with => nil }
440: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
441:
442: raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp)
443:
444: validates_each(attr_names, configuration) do |record, attr_name, value|
445: record.errors.add(attr_name, configuration[:message]) unless value.to_s =~ configuration[:with]
446: end
447: 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)
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 460
460: def validates_inclusion_of(*attr_names)
461: configuration = { :message => ActiveRecord::Errors.default_error_messages[:inclusion], :on => :save }
462: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
463:
464: enum = configuration[:in] || configuration[:within]
465:
466: 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?")
467:
468: validates_each(attr_names, configuration) do |record, attr_name, value|
469: record.errors.add(attr_name, configuration[:message]) unless enum.include?(value)
470: end
471: 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)
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 354
354: def validates_length_of(*attrs)
355: # Merge given options with defaults.
356: options = DEFAULT_SIZE_VALIDATION_OPTIONS.dup
357: options.update(attrs.pop.symbolize_keys) if attrs.last.is_a?(Hash)
358:
359: # Ensure that one and only one range option is specified.
360: range_options = ALL_RANGE_OPTIONS & options.keys
361: case range_options.size
362: when 0
363: raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.'
364: when 1
365: # Valid number of options; do nothing.
366: else
367: raise ArgumentError, 'Too many range options specified. Choose only one.'
368: end
369:
370: # Get range option and value.
371: option = range_options.first
372: option_value = options[range_options.first]
373:
374: # Declare different validations per option.
375:
376: validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" }
377: message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }
378:
379: case option
380: when :within, :in
381: raise ArgumentError, ':within must be a Range' unless option_value.is_a?(Range) # '
382: validates_length_of attrs, :minimum => option_value.begin, :allow_nil => options[:allow_nil]
383: validates_length_of attrs, :maximum => option_value.end, :allow_nil => options[:allow_nil]
384: when :is, :minimum, :maximum
385: raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0 # '
386: message = options[:message] || options[message_options[option]]
387: message = (message % option_value) rescue message
388: validates_each(attrs, options) do |record, attr, value|
389: record.errors.add(attr, message) if value.nil? or !value.size.method(validity_checks[option])[option_value]
390: end
391: end
392: 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)
- allow_nil Skip validation if attribute is nil (default is false). Notice that for fixnum and float columsn empty strings are converted to nil
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 517
517: def validates_numericality_of(*attr_names)
518: configuration = { :message => ActiveRecord::Errors.default_error_messages[:not_a_number], :on => :save,
519: :only_integer => false, :allow_nil => false }
520: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
521:
522: if configuration[:only_integer]
523: validates_each(attr_names,configuration) do |record, attr_name,value|
524: record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_before_type_cast").to_s =~ /^[+-]?\d+$/
525: end
526: else
527: validates_each(attr_names,configuration) do |record, attr_name,value|
528: begin
529: Kernel.Float(record.send("#{attr_name}_before_type_cast").to_s)
530: rescue ArgumentError, TypeError
531: record.errors.add(attr_name, configuration[:message])
532: end
533: end
534: end
535: 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)
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 317
317: def validates_presence_of(*attr_names)
318: configuration = { :message => ActiveRecord::Errors.default_error_messages[:empty], :on => :save }
319: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
320:
321: # can't use validates_each here, because it cannot cope with non-existant attributes,
322: # while errors.add_on_empty can
323: attr_names.each do |attr_name|
324: send(validation_method(configuration[:on])) do |record|
325: record.errors.add_on_empty(attr_name,configuration[:message])
326: end
327: end
328: end
Alias for validates_length_of
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"
[ show source ]
# File vendor/rails/activerecord/lib/active_record/validations.rb, line 410
410: def validates_uniqueness_of(*attr_names)
411: configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] }
412: configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
413:
414: if scope = configuration[:scope]
415: validates_each(attr_names,configuration) do |record, attr_name, value|
416: record.errors.add(attr_name, configuration[:message]) if record.class.find_first(record.new_record? ? ["#{attr_name} = ? AND #{scope} = ?", record.send(attr_name), record.send(scope)] : ["#{attr_name} = ? AND #{record.class.primary_key} <> ? AND #{scope} = ?", record.send(attr_name), record.send(:id), record.send(scope)])
417: end
418: else
419: validates_each(attr_names,configuration) do |record, attr_name, value|
420: record.errors.add(attr_name, configuration[:message]) if record.class.find_first(record.new_record? ? ["#{attr_name} = ?", record.send(attr_name)] : ["#{attr_name} = ? AND #{record.class.primary_key} <> ?", record.send(attr_name), record.send(:id) ] )
421: end
422: end
423: end