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:
commit
d15069316f
15 changed files with 83 additions and 8 deletions
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue