1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #2563 from bogdan/internal_validation

Implemented strict validation concept
This commit is contained in:
José Valim 2011-08-25 07:10:16 -07:00
commit d15069316f
15 changed files with 83 additions and 8 deletions

View file

@ -1,3 +1,5 @@
* Add ability to define strict validation(with :strict => true option) that always raises exception when fails [Bogdan Gusiev]
* Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" [Grant Hutchins, Peter Jaros]
* Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior [Bogdan Gusiev]

View file

@ -63,7 +63,7 @@ module ActiveModel
class Errors
include Enumerable
CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank]
CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank, :strict]
attr_reader :messages
@ -218,6 +218,9 @@ module ActiveModel
elsif message.is_a?(Proc)
message = message.call
end
if options[:strict]
raise ActiveModel::StrictValidationFailed, message
end
self[attribute] << message
end
@ -319,4 +322,7 @@ module ActiveModel
I18n.translate(key, options)
end
end
class StrictValidationFailed < StandardError
end
end

View file

@ -58,6 +58,8 @@ module ActiveModel
# <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>).
# The method, proc or string should return or evaluate to a true or
# false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
def validates_acceptance_of(*attr_names)
validates_with AcceptanceValidator, _merge_attributes(attr_names)
end

View file

@ -58,6 +58,8 @@ module ActiveModel
# <tt>:unless => :skip_validation</tt>, or
# <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
def validates_confirmation_of(*attr_names)
validates_with ConfirmationValidator, _merge_attributes(attr_names)
end

View file

@ -59,6 +59,8 @@ module ActiveModel
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
def validates_exclusion_of(*attr_names)
validates_with ExclusionValidator, _merge_attributes(attr_names)
end

View file

@ -84,6 +84,8 @@ module ActiveModel
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
def validates_format_of(*attr_names)
validates_with FormatValidator, _merge_attributes(attr_names)
end

View file

@ -59,6 +59,8 @@ module ActiveModel
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
def validates_inclusion_of(*attr_names)
validates_with InclusionValidator, _merge_attributes(attr_names)
end

View file

@ -96,6 +96,8 @@ module ActiveModel
# * <tt>:tokenizer</tt> - Specifies how to split up the attribute string. (e.g. <tt>:tokenizer => lambda {|str| str.scan(/\w+/)}</tt> to
# count words as in above example.)
# Defaults to <tt>lambda{ |value| value.split(//) }</tt> which counts individual characters.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
def validates_length_of(*attr_names)
validates_with LengthValidator, _merge_attributes(attr_names)
end

View file

@ -107,6 +107,8 @@ module ActiveModel
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
#
# The following checks can also be supplied with a proc or a symbol which corresponds to a method:
# * <tt>:greater_than</tt>

View file

@ -35,6 +35,8 @@ module ActiveModel
# * <tt>unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>).
# The method, proc or string should return or evaluate to a true or false value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
#
def validates_presence_of(*attr_names)
validates_with PresenceValidator, _merge_attributes(attr_names)

View file

@ -70,8 +70,8 @@ module ActiveModel
# validator's initializer as +options[:in]+ while other types including
# regular expressions and strings are passed as +options[:with]+
#
# Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+ and +:allow_nil+ can be given
# to one specific validator, as a hash:
# Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+ and +:strict+
# can be given to one specific validator, as a hash:
#
# validates :password, :presence => { :if => :password_required? }, :confirmation => true
#
@ -101,12 +101,24 @@ module ActiveModel
end
end
# This method is used to define validation that can not be corrected by end user
# and is considered exceptional.
# So each validator defined with bang or <tt>:strict</tt> option set to <tt>true</tt>
# will always raise <tt>ActiveModel::InternalValidationFailed</tt> instead of adding error
# when validation fails
# See <tt>validates</tt> for more information about validation itself.
def validates!(*attributes)
options = attributes.extract_options!
options[:strict] = true
validates(*(attributes << options))
end
protected
# When creating custom validators, it might be useful to be able to specify
# additional default keys. This can be done by overwriting this method.
def _validates_default_keys
[ :if, :unless, :on, :allow_blank, :allow_nil ]
[ :if, :unless, :on, :allow_blank, :allow_nil , :strict]
end
def _parse_validates_options(options) #:nodoc:

View file

@ -61,7 +61,9 @@ module ActiveModel
# (e.g. <tt>:unless => :skip_validation</tt>, or
# <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>).
# The method, proc or string should return or evaluate to a true or false value.
#
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information
# If you pass any additional configuration options, they will be passed
# to the class and available as <tt>options</tt>:
#
@ -140,4 +142,4 @@ module ActiveModel
end
end
end
end
end

View file

@ -297,4 +297,37 @@ class ValidationsTest < ActiveModel::TestCase
assert auto.valid?
end
def test_strict_validation_in_validates
Topic.validates :title, :strict => true, :presence => true
assert_raises ActiveModel::StrictValidationFailed do
Topic.new.valid?
end
end
def test_strict_validation_not_fails
Topic.validates :title, :strict => true, :presence => true
assert Topic.new(:title => "hello").valid?
end
def test_strict_validation_particular_validator
Topic.validates :title, :presence => {:strict => true}
assert_raises ActiveModel::StrictValidationFailed do
Topic.new.valid?
end
end
def test_strict_validation_in_custom_validator_helper
Topic.validates_presence_of :title, :strict => true
assert_raises ActiveModel::StrictValidationFailed do
Topic.new.valid?
end
end
def test_validates_with_bang
Topic.validates! :title, :presence => true
assert_raises ActiveModel::StrictValidationFailed do
Topic.new.valid?
end
end
end

View file

@ -183,20 +183,23 @@ Validations module adds the ability to class objects to validate them in Active
class Person
include ActiveModel::Validations
attr_accessor :name, :email
attr_accessor :name, :email, :token
validates :name, :presence => true
validates_format_of :email, :with => /^([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})$/i
validates! :token, :presence => true
end
person = Person.new
person = Person.new(:token => "2b1f325")
person.valid? #=> false
person.name = 'vishnu'
person.email = 'me'
person.valid? #=> false
person.email = 'me@vishnuatrai.com'
person.valid? #=> true
person.token = nil
person.valid? #=> raises ActiveModel::StrictValidationFailed
</ruby>
h3. Changelog

View file

@ -1270,6 +1270,7 @@ The +after_commit+ and +after_rollback+ callbacks are guaranteed to be called fo
h3. Changelog
* August 24, 2011: Add strict validation usage example. "Bogdan Gusiev":http://gusiev.com
* February 17, 2011: Add description of transaction callbacks.
* July 20, 2010: Fixed typos and rephrased some paragraphs for clarity. "Jaime Iniesta":http://jaimeiniesta.com
* May 24, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com