activemodel 3.2.22.5 → 4.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +85 -64
- data/MIT-LICENSE +1 -1
- data/README.rdoc +61 -24
- data/lib/active_model.rb +21 -11
- data/lib/active_model/attribute_methods.rb +150 -125
- data/lib/active_model/callbacks.rb +49 -34
- data/lib/active_model/conversion.rb +39 -19
- data/lib/active_model/deprecated_mass_assignment_security.rb +21 -0
- data/lib/active_model/dirty.rb +48 -32
- data/lib/active_model/errors.rb +176 -88
- data/lib/active_model/forbidden_attributes_protection.rb +27 -0
- data/lib/active_model/lint.rb +42 -55
- data/lib/active_model/locale/en.yml +3 -1
- data/lib/active_model/model.rb +97 -0
- data/lib/active_model/naming.rb +191 -51
- data/lib/active_model/railtie.rb +11 -1
- data/lib/active_model/secure_password.rb +55 -25
- data/lib/active_model/serialization.rb +51 -27
- data/lib/active_model/serializers/json.rb +83 -46
- data/lib/active_model/serializers/xml.rb +46 -12
- data/lib/active_model/test_case.rb +0 -12
- data/lib/active_model/translation.rb +9 -10
- data/lib/active_model/validations.rb +154 -52
- data/lib/active_model/validations/absence.rb +31 -0
- data/lib/active_model/validations/acceptance.rb +10 -22
- data/lib/active_model/validations/callbacks.rb +78 -25
- data/lib/active_model/validations/clusivity.rb +41 -0
- data/lib/active_model/validations/confirmation.rb +13 -23
- data/lib/active_model/validations/exclusion.rb +26 -55
- data/lib/active_model/validations/format.rb +44 -34
- data/lib/active_model/validations/inclusion.rb +22 -52
- data/lib/active_model/validations/length.rb +48 -49
- data/lib/active_model/validations/numericality.rb +30 -32
- data/lib/active_model/validations/presence.rb +12 -22
- data/lib/active_model/validations/validates.rb +68 -36
- data/lib/active_model/validations/with.rb +28 -23
- data/lib/active_model/validator.rb +22 -22
- data/lib/active_model/version.rb +4 -4
- metadata +23 -24
- data/lib/active_model/mass_assignment_security.rb +0 -237
- data/lib/active_model/mass_assignment_security/permission_set.rb +0 -40
- data/lib/active_model/mass_assignment_security/sanitizer.rb +0 -59
- data/lib/active_model/observer_array.rb +0 -147
- data/lib/active_model/observing.rb +0 -252
@@ -1,38 +1,16 @@
|
|
1
|
-
require
|
1
|
+
require "active_model/validations/clusivity"
|
2
2
|
|
3
3
|
module ActiveModel
|
4
|
-
# == Active Model Inclusion Validator
|
5
|
-
module Validations
|
6
|
-
class InclusionValidator < EachValidator
|
7
|
-
ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
|
8
|
-
"and must be supplied as the :in (or :within) option of the configuration hash"
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
5
|
+
module Validations
|
6
|
+
class InclusionValidator < EachValidator # :nodoc:
|
7
|
+
include Clusivity
|
15
8
|
|
16
9
|
def validate_each(record, attribute, value)
|
17
|
-
|
18
|
-
unless exclusions.send(inclusion_method(exclusions), value)
|
10
|
+
unless include?(record, value)
|
19
11
|
record.errors.add(attribute, :inclusion, options.except(:in, :within).merge!(:value => value))
|
20
12
|
end
|
21
13
|
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def delimiter
|
26
|
-
@delimiter ||= options[:in] || options[:within]
|
27
|
-
end
|
28
|
-
|
29
|
-
# In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible
|
30
|
-
# values in the range for equality, so it may be slow for large ranges. The new
|
31
|
-
# <tt>Range#cover?</tt> uses the previous logic of comparing a value with the
|
32
|
-
# range endpoints.
|
33
|
-
def inclusion_method(enumerable)
|
34
|
-
enumerable.is_a?(Range) ? :cover? : :include?
|
35
|
-
end
|
36
14
|
end
|
37
15
|
|
38
16
|
module HelperMethods
|
@@ -40,37 +18,29 @@ module ActiveModel
|
|
40
18
|
# particular enumerable object.
|
41
19
|
#
|
42
20
|
# class Person < ActiveRecord::Base
|
43
|
-
# validates_inclusion_of :gender, :
|
44
|
-
# validates_inclusion_of :age, :
|
45
|
-
# validates_inclusion_of :format, :
|
46
|
-
# validates_inclusion_of :states, :
|
21
|
+
# validates_inclusion_of :gender, in: %w( m f )
|
22
|
+
# validates_inclusion_of :age, in: 0..99
|
23
|
+
# validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list"
|
24
|
+
# validates_inclusion_of :states, in: ->(person) { STATES[person.country] }
|
25
|
+
# validates_inclusion_of :karma, in: :available_karmas
|
47
26
|
# end
|
48
27
|
#
|
49
28
|
# Configuration options:
|
50
29
|
# * <tt>:in</tt> - An enumerable object of available items. This can be
|
51
|
-
# supplied as a proc or
|
52
|
-
# is a range the test is performed with <tt>Range#cover?</tt
|
53
|
-
#
|
30
|
+
# supplied as a proc, lambda or symbol which returns an enumerable. If the
|
31
|
+
# enumerable is a range the test is performed with <tt>Range#cover?</tt>,
|
32
|
+
# otherwise with <tt>include?</tt>.
|
54
33
|
# * <tt>:within</tt> - A synonym(or alias) for <tt>:in</tt>
|
55
|
-
# * <tt>:message</tt> - Specifies a custom error message (default is: "is
|
56
|
-
# included in the list").
|
57
|
-
# * <tt>:allow_nil</tt> - If set to true
|
58
|
-
# is +nil+ (default is +false+).
|
59
|
-
# * <tt>:allow_blank</tt> - If set to true
|
34
|
+
# * <tt>:message</tt> - Specifies a custom error message (default is: "is
|
35
|
+
# not included in the list").
|
36
|
+
# * <tt>:allow_nil</tt> - If set to +true+, skips this validation if the
|
37
|
+
# attribute is +nil+ (default is +false+).
|
38
|
+
# * <tt>:allow_blank</tt> - If set to +true+, skips this validation if the
|
60
39
|
# attribute is blank (default is +false+).
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
|
66
|
-
# <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
|
67
|
-
# or string should return or evaluate to a true or false value.
|
68
|
-
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
|
69
|
-
# if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
|
70
|
-
# or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
|
71
|
-
# proc or string should return or evaluate to a true or false value.
|
72
|
-
# * <tt>:strict</tt> - Specifies whether validation should be strict.
|
73
|
-
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
|
40
|
+
#
|
41
|
+
# There is also a list of default options supported by every validator:
|
42
|
+
# +:if+, +:unless+, +:on+ and +:strict+.
|
43
|
+
# See <tt>ActiveModel::Validation#validates</tt> for more information
|
74
44
|
def validates_inclusion_of(*attr_names)
|
75
45
|
validates_with InclusionValidator, _merge_attributes(attr_names)
|
76
46
|
end
|
@@ -1,9 +1,8 @@
|
|
1
|
-
require "active_support/core_ext/string/encoding"
|
2
|
-
|
3
1
|
module ActiveModel
|
4
|
-
|
2
|
+
|
3
|
+
# == Active \Model Length \Validator
|
5
4
|
module Validations
|
6
|
-
class LengthValidator < EachValidator
|
5
|
+
class LengthValidator < EachValidator # :nodoc:
|
7
6
|
MESSAGES = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }.freeze
|
8
7
|
CHECKS = { :is => :==, :minimum => :>=, :maximum => :<= }.freeze
|
9
8
|
|
@@ -12,8 +11,11 @@ module ActiveModel
|
|
12
11
|
def initialize(options)
|
13
12
|
if range = (options.delete(:in) || options.delete(:within))
|
14
13
|
raise ArgumentError, ":in and :within must be a Range" unless range.is_a?(Range)
|
15
|
-
options[:minimum], options[:maximum] = range.
|
16
|
-
|
14
|
+
options[:minimum], options[:maximum] = range.min, range.max
|
15
|
+
end
|
16
|
+
|
17
|
+
if options[:allow_blank] == false && options[:minimum].nil? && options[:is].nil?
|
18
|
+
options[:minimum] = 1
|
17
19
|
end
|
18
20
|
|
19
21
|
super
|
@@ -29,8 +31,8 @@ module ActiveModel
|
|
29
31
|
keys.each do |key|
|
30
32
|
value = options[key]
|
31
33
|
|
32
|
-
unless value.is_a?(Integer) && value >= 0
|
33
|
-
raise ArgumentError, ":#{key} must be a nonnegative Integer"
|
34
|
+
unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY
|
35
|
+
raise ArgumentError, ":#{key} must be a nonnegative Integer or Infinity"
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -38,12 +40,15 @@ module ActiveModel
|
|
38
40
|
def validate_each(record, attribute, value)
|
39
41
|
value = tokenize(value)
|
40
42
|
value_length = value.respond_to?(:length) ? value.length : value.to_s.length
|
43
|
+
errors_options = options.except(*RESERVED_OPTIONS)
|
41
44
|
|
42
45
|
CHECKS.each do |key, validity_check|
|
43
46
|
next unless check_value = options[key]
|
44
|
-
next if value_length.send(validity_check, check_value)
|
45
47
|
|
46
|
-
|
48
|
+
if !value.nil? || skip_nil_check?(key)
|
49
|
+
next if value_length.send(validity_check, check_value)
|
50
|
+
end
|
51
|
+
|
47
52
|
errors_options[:count] = check_value
|
48
53
|
|
49
54
|
default_message = options[MESSAGES[key]]
|
@@ -56,67 +61,61 @@ module ActiveModel
|
|
56
61
|
private
|
57
62
|
|
58
63
|
def tokenize(value)
|
59
|
-
if value.kind_of?(String)
|
60
|
-
|
61
|
-
options[:tokenizer].call(value)
|
62
|
-
elsif !value.encoding_aware?
|
63
|
-
value.mb_chars
|
64
|
-
end
|
64
|
+
if options[:tokenizer] && value.kind_of?(String)
|
65
|
+
options[:tokenizer].call(value)
|
65
66
|
end || value
|
66
67
|
end
|
68
|
+
|
69
|
+
def skip_nil_check?(key)
|
70
|
+
key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil?
|
71
|
+
end
|
67
72
|
end
|
68
73
|
|
69
74
|
module HelperMethods
|
70
|
-
|
71
|
-
#
|
75
|
+
|
76
|
+
# Validates that the specified attribute matches the length restrictions
|
77
|
+
# supplied. Only one option can be used at a time:
|
72
78
|
#
|
73
79
|
# class Person < ActiveRecord::Base
|
74
|
-
# validates_length_of :first_name, :
|
75
|
-
# validates_length_of :last_name, :
|
76
|
-
# validates_length_of :fax, :
|
77
|
-
# validates_length_of :phone, :
|
78
|
-
# validates_length_of :user_name, :
|
79
|
-
# validates_length_of :zip_code, :
|
80
|
-
# validates_length_of :smurf_leader, :
|
81
|
-
# validates_length_of :essay, :
|
82
|
-
# :
|
80
|
+
# validates_length_of :first_name, maximum: 30
|
81
|
+
# validates_length_of :last_name, maximum: 30, message: "less than 30 if you don't mind"
|
82
|
+
# validates_length_of :fax, in: 7..32, allow_nil: true
|
83
|
+
# validates_length_of :phone, in: 7..32, allow_blank: true
|
84
|
+
# validates_length_of :user_name, within: 6..20, too_long: 'pick a shorter name', too_short: 'pick a longer name'
|
85
|
+
# validates_length_of :zip_code, minimum: 5, too_short: 'please enter at least 5 characters'
|
86
|
+
# validates_length_of :smurf_leader, is: 4, message: "papa is spelled with 4 characters... don't play me."
|
87
|
+
# validates_length_of :essay, minimum: 100, too_short: 'Your essay must be at least 100 words.',
|
88
|
+
# tokenizer: ->(str) { str.scan(/\w+/) }
|
83
89
|
# end
|
84
90
|
#
|
85
91
|
# Configuration options:
|
86
92
|
# * <tt>:minimum</tt> - The minimum size of the attribute.
|
87
|
-
# * <tt>:maximum</tt> - The maximum size of the attribute.
|
93
|
+
# * <tt>:maximum</tt> - The maximum size of the attribute. Allows +nil+ by
|
94
|
+
# default if not used with :minimum.
|
88
95
|
# * <tt>:is</tt> - The exact size of the attribute.
|
89
|
-
# * <tt>:within</tt> - A range specifying the minimum and maximum size of
|
90
|
-
# attribute.
|
91
|
-
# * <tt>:in</tt> - A synonym(or alias) for <tt>:within</tt>.
|
96
|
+
# * <tt>:within</tt> - A range specifying the minimum and maximum size of
|
97
|
+
# the attribute.
|
98
|
+
# * <tt>:in</tt> - A synonym (or alias) for <tt>:within</tt>.
|
92
99
|
# * <tt>:allow_nil</tt> - Attribute may be +nil+; skip validation.
|
93
100
|
# * <tt>:allow_blank</tt> - Attribute may be blank; skip validation.
|
94
101
|
# * <tt>:too_long</tt> - The error message if the attribute goes over the
|
95
102
|
# maximum (default is: "is too long (maximum is %{count} characters)").
|
96
103
|
# * <tt>:too_short</tt> - The error message if the attribute goes under the
|
97
104
|
# minimum (default is: "is too short (min is %{count} characters)").
|
98
|
-
# * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt>
|
99
|
-
# and the attribute is the wrong size (default is: "is the wrong
|
100
|
-
# should be %{count} characters)").
|
105
|
+
# * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt>
|
106
|
+
# method and the attribute is the wrong size (default is: "is the wrong
|
107
|
+
# length (should be %{count} characters)").
|
101
108
|
# * <tt>:message</tt> - The error message to use for a <tt>:minimum</tt>,
|
102
109
|
# <tt>:maximum</tt>, or <tt>:is</tt> violation. An alias of the appropriate
|
103
110
|
# <tt>too_long</tt>/<tt>too_short</tt>/<tt>wrong_length</tt> message.
|
104
|
-
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
105
|
-
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
106
|
-
# and <tt>:update</tt>.
|
107
|
-
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if
|
108
|
-
# the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
|
109
|
-
# <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
|
110
|
-
# or string should return or evaluate to a true or false value.
|
111
|
-
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
|
112
|
-
# if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
|
113
|
-
# or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
|
114
|
-
# method, proc or string should return or evaluate to a true or false value.
|
115
111
|
# * <tt>:tokenizer</tt> - Specifies how to split up the attribute string.
|
116
|
-
# (e.g. <tt
|
117
|
-
# as in above example). Defaults to <tt
|
118
|
-
#
|
119
|
-
#
|
112
|
+
# (e.g. <tt>tokenizer: ->(str) { str.scan(/\w+/) }</tt> to count words
|
113
|
+
# as in above example). Defaults to <tt>->(value) { value.split(//) }</tt>
|
114
|
+
# which counts individual characters.
|
115
|
+
#
|
116
|
+
# There is also a list of default options supported by every validator:
|
117
|
+
# +:if+, +:unless+, +:on+ and +:strict+.
|
118
|
+
# See <tt>ActiveModel::Validation#validates</tt> for more information
|
120
119
|
def validates_length_of(*attr_names)
|
121
120
|
validates_with LengthValidator, _merge_attributes(attr_names)
|
122
121
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module ActiveModel
|
2
|
-
|
2
|
+
|
3
3
|
module Validations
|
4
|
-
class NumericalityValidator < EachValidator
|
4
|
+
class NumericalityValidator < EachValidator # :nodoc:
|
5
5
|
CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=,
|
6
6
|
:equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=,
|
7
|
-
:odd => :odd?, :even => :even
|
7
|
+
:odd => :odd?, :even => :even?, :other_than => :!= }.freeze
|
8
8
|
|
9
9
|
RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
|
10
10
|
|
@@ -17,9 +17,9 @@ module ActiveModel
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def validate_each(record, attr_name, value)
|
20
|
-
before_type_cast = "#{attr_name}_before_type_cast"
|
20
|
+
before_type_cast = :"#{attr_name}_before_type_cast"
|
21
21
|
|
22
|
-
raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast
|
22
|
+
raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast)
|
23
23
|
raw_value ||= value
|
24
24
|
|
25
25
|
return if options[:allow_nil] && raw_value.nil?
|
@@ -78,46 +78,44 @@ module ActiveModel
|
|
78
78
|
end
|
79
79
|
|
80
80
|
module HelperMethods
|
81
|
-
# Validates whether the value of the specified attribute is numeric by
|
82
|
-
# a float with Kernel.Float (if <tt>only_integer</tt>
|
83
|
-
# <tt>/\A[\+\-]?\d+\Z/</tt>
|
81
|
+
# Validates whether the value of the specified attribute is numeric by
|
82
|
+
# trying to convert it to a float with Kernel.Float (if <tt>only_integer</tt>
|
83
|
+
# is +false+) or applying it to the regular expression <tt>/\A[\+\-]?\d+\Z/</tt>
|
84
|
+
# (if <tt>only_integer</tt> is set to +true+).
|
84
85
|
#
|
85
86
|
# class Person < ActiveRecord::Base
|
86
|
-
# validates_numericality_of :value, :
|
87
|
+
# validates_numericality_of :value, on: :create
|
87
88
|
# end
|
88
89
|
#
|
89
90
|
# Configuration options:
|
90
91
|
# * <tt>:message</tt> - A custom error message (default is: "is not a number").
|
91
|
-
# * <tt>:
|
92
|
-
#
|
93
|
-
# and <tt>:update</tt>.
|
94
|
-
# * <tt>:only_integer</tt> - Specifies whether the value has to be an integer, e.g. an integral value (default is +false+).
|
92
|
+
# * <tt>:only_integer</tt> - Specifies whether the value has to be an
|
93
|
+
# integer, e.g. an integral value (default is +false+).
|
95
94
|
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default is
|
96
95
|
# +false+). Notice that for fixnum and float columns empty strings are
|
97
96
|
# converted to +nil+.
|
98
97
|
# * <tt>:greater_than</tt> - Specifies the value must be greater than the
|
99
98
|
# supplied value.
|
100
|
-
# * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be
|
101
|
-
# than or equal the supplied value.
|
102
|
-
# * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied
|
103
|
-
# * <tt>:less_than</tt> - Specifies the value must be less than the supplied
|
99
|
+
# * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be
|
100
|
+
# greater than or equal the supplied value.
|
101
|
+
# * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied
|
104
102
|
# value.
|
105
|
-
# * <tt>:
|
106
|
-
#
|
103
|
+
# * <tt>:less_than</tt> - Specifies the value must be less than the
|
104
|
+
# supplied value.
|
105
|
+
# * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less
|
106
|
+
# than or equal the supplied value.
|
107
|
+
# * <tt>:other_than</tt> - Specifies the value must be other than the
|
108
|
+
# supplied value.
|
107
109
|
# * <tt>:odd</tt> - Specifies the value must be an odd number.
|
108
110
|
# * <tt>:even</tt> - Specifies the value must be an even number.
|
109
|
-
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
|
110
|
-
# if the validation should occur (e.g. <tt>:if => :allow_validation</tt>,
|
111
|
-
# or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method,
|
112
|
-
# proc or string should return or evaluate to a true or false value.
|
113
|
-
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
|
114
|
-
# if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
|
115
|
-
# or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
|
116
|
-
# proc or string should return or evaluate to a true or false value.
|
117
|
-
# * <tt>:strict</tt> - Specifies whether validation should be strict.
|
118
|
-
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
|
119
111
|
#
|
120
|
-
#
|
112
|
+
# There is also a list of default options supported by every validator:
|
113
|
+
# +:if+, +:unless+, +:on+ and +:strict+ .
|
114
|
+
# See <tt>ActiveModel::Validation#validates</tt> for more information
|
115
|
+
#
|
116
|
+
# The following checks can also be supplied with a proc or a symbol which
|
117
|
+
# corresponds to a method:
|
118
|
+
#
|
121
119
|
# * <tt>:greater_than</tt>
|
122
120
|
# * <tt>:greater_than_or_equal_to</tt>
|
123
121
|
# * <tt>:equal_to</tt>
|
@@ -127,8 +125,8 @@ module ActiveModel
|
|
127
125
|
# For example:
|
128
126
|
#
|
129
127
|
# class Person < ActiveRecord::Base
|
130
|
-
# validates_numericality_of :width, :
|
131
|
-
# validates_numericality_of :width, :
|
128
|
+
# validates_numericality_of :width, less_than: ->(person) { person.height }
|
129
|
+
# validates_numericality_of :width, greater_than: :minimum_weight
|
132
130
|
# end
|
133
131
|
def validates_numericality_of(*attr_names)
|
134
132
|
validates_with NumericalityValidator, _merge_attributes(attr_names)
|
@@ -1,17 +1,16 @@
|
|
1
|
-
require 'active_support/core_ext/object/blank'
|
2
1
|
|
3
2
|
module ActiveModel
|
4
|
-
|
3
|
+
|
5
4
|
module Validations
|
6
|
-
class PresenceValidator < EachValidator
|
7
|
-
def
|
8
|
-
record.errors.
|
5
|
+
class PresenceValidator < EachValidator # :nodoc:
|
6
|
+
def validate_each(record, attr_name, value)
|
7
|
+
record.errors.add(attr_name, :blank, options) if value.blank?
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
12
11
|
module HelperMethods
|
13
12
|
# Validates that the specified attributes are not blank (as defined by
|
14
|
-
# Object#blank?). Happens by default on save.
|
13
|
+
# Object#blank?). Happens by default on save.
|
15
14
|
#
|
16
15
|
# class Person < ActiveRecord::Base
|
17
16
|
# validates_presence_of :first_name
|
@@ -19,28 +18,19 @@ module ActiveModel
|
|
19
18
|
#
|
20
19
|
# The first_name attribute must be in the object and it cannot be blank.
|
21
20
|
#
|
22
|
-
# If you want to validate the presence of a boolean field (where the real
|
23
|
-
# are true and false), you will want to use
|
24
|
-
# :in
|
21
|
+
# If you want to validate the presence of a boolean field (where the real
|
22
|
+
# values are +true+ and +false+), you will want to use
|
23
|
+
# <tt>validates_inclusion_of :field_name, in: [true, false]</tt>.
|
25
24
|
#
|
26
25
|
# This is due to the way Object#blank? handles boolean values:
|
27
26
|
# <tt>false.blank? # => true</tt>.
|
28
27
|
#
|
29
28
|
# Configuration options:
|
30
29
|
# * <tt>:message</tt> - A custom error message (default is: "can't be blank").
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# the validation should occur (e.g. <tt>:if => :allow_validation</tt>, or
|
36
|
-
# <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The method, proc
|
37
|
-
# or string should return or evaluate to a true or false value.
|
38
|
-
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
|
39
|
-
# if the validation should not occur (e.g. <tt>:unless => :skip_validation</tt>,
|
40
|
-
# or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
|
41
|
-
# proc or string should return or evaluate to a true or false value.
|
42
|
-
# * <tt>:strict</tt> - Specifies whether validation should be strict.
|
43
|
-
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
|
30
|
+
#
|
31
|
+
# There is also a list of default options supported by every validator:
|
32
|
+
# +:if+, +:unless+, +:on+ and +:strict+.
|
33
|
+
# See <tt>ActiveModel::Validation#validates</tt> for more information
|
44
34
|
def validates_presence_of(*attr_names)
|
45
35
|
validates_with PresenceValidator, _merge_attributes(attr_names)
|
46
36
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/hash/slice'
|
2
2
|
|
3
3
|
module ActiveModel
|
4
|
-
# == Active Model validates method
|
5
4
|
module Validations
|
6
5
|
module ClassMethods
|
7
6
|
# This method is a shortcut to all default validators and any custom
|
@@ -11,18 +10,18 @@ module ActiveModel
|
|
11
10
|
#
|
12
11
|
# Examples of using the default rails validators:
|
13
12
|
#
|
14
|
-
# validates :terms, :
|
15
|
-
# validates :password, :
|
16
|
-
# validates :username, :
|
17
|
-
# validates :email, :
|
18
|
-
# validates :age, :
|
19
|
-
# validates :first_name, :
|
20
|
-
# validates :age, :
|
21
|
-
# validates :username, :
|
22
|
-
# validates :username, :
|
13
|
+
# validates :terms, acceptance: true
|
14
|
+
# validates :password, confirmation: true
|
15
|
+
# validates :username, exclusion: { in: %w(admin superuser) }
|
16
|
+
# validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, on: :create }
|
17
|
+
# validates :age, inclusion: { in: 0..9 }
|
18
|
+
# validates :first_name, length: { maximum: 30 }
|
19
|
+
# validates :age, numericality: true
|
20
|
+
# validates :username, presence: true
|
21
|
+
# validates :username, uniqueness: true
|
23
22
|
#
|
24
23
|
# The power of the +validates+ method comes when using custom validators
|
25
|
-
# and default validators in one call for a given attribute
|
24
|
+
# and default validators in one call for a given attribute.
|
26
25
|
#
|
27
26
|
# class EmailValidator < ActiveModel::EachValidator
|
28
27
|
# def validate_each(record, attribute, value)
|
@@ -35,12 +34,12 @@ module ActiveModel
|
|
35
34
|
# include ActiveModel::Validations
|
36
35
|
# attr_accessor :name, :email
|
37
36
|
#
|
38
|
-
# validates :name, :
|
39
|
-
# validates :email, :
|
37
|
+
# validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
|
38
|
+
# validates :email, presence: true, email: true
|
40
39
|
# end
|
41
40
|
#
|
42
41
|
# Validator classes may also exist within the class being validated
|
43
|
-
# allowing custom modules of validators to be included as needed
|
42
|
+
# allowing custom modules of validators to be included as needed.
|
44
43
|
#
|
45
44
|
# class Film
|
46
45
|
# include ActiveModel::Validations
|
@@ -51,43 +50,64 @@ module ActiveModel
|
|
51
50
|
# end
|
52
51
|
# end
|
53
52
|
#
|
54
|
-
# validates :name, :
|
53
|
+
# validates :name, title: true
|
55
54
|
# end
|
56
55
|
#
|
57
|
-
# Additionally validator classes may be in another namespace and still
|
56
|
+
# Additionally validator classes may be in another namespace and still
|
57
|
+
# used within any class.
|
58
58
|
#
|
59
59
|
# validates :name, :'film/title' => true
|
60
60
|
#
|
61
|
-
# The validators hash can also handle regular expressions, ranges,
|
62
|
-
#
|
61
|
+
# The validators hash can also handle regular expressions, ranges, arrays
|
62
|
+
# and strings in shortcut form.
|
63
63
|
#
|
64
|
-
# validates :email, :
|
65
|
-
# validates :gender, :
|
66
|
-
# validates :password, :
|
64
|
+
# validates :email, format: /@/
|
65
|
+
# validates :gender, inclusion: %w(male female)
|
66
|
+
# validates :password, length: 6..20
|
67
67
|
#
|
68
68
|
# When using shortcut form, ranges and arrays are passed to your
|
69
|
-
# validator's initializer as
|
70
|
-
# regular expressions and strings are passed as
|
69
|
+
# validator's initializer as <tt>options[:in]</tt> while other types
|
70
|
+
# including regular expressions and strings are passed as <tt>options[:with]</tt>.
|
71
71
|
#
|
72
|
-
#
|
73
|
-
# can be given to one specific validator, as a hash:
|
72
|
+
# There is also a list of options that could be used along with validators:
|
74
73
|
#
|
75
|
-
#
|
74
|
+
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
75
|
+
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
76
|
+
# and <tt>:update</tt>.
|
77
|
+
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
|
78
|
+
# if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
|
79
|
+
# or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
|
80
|
+
# proc or string should return or evaluate to a +true+ or +false+ value.
|
81
|
+
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
|
82
|
+
# if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
|
83
|
+
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
|
84
|
+
# method, proc or string should return or evaluate to a +true+ or
|
85
|
+
# +false+ value.
|
86
|
+
# * <tt>:strict</tt> - if the <tt>:strict</tt> option is set to true
|
87
|
+
# will raise ActiveModel::StrictValidationFailed instead of adding the error.
|
88
|
+
# <tt>:strict</tt> option can also be set to any other exception.
|
76
89
|
#
|
77
|
-
#
|
90
|
+
# Example:
|
78
91
|
#
|
79
|
-
# validates :password, :
|
92
|
+
# validates :password, presence: true, confirmation: true, if: :password_required?
|
93
|
+
# validates :token, uniqueness: true, strict: TokenGenerationException
|
80
94
|
#
|
95
|
+
#
|
96
|
+
# Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+, +:strict+
|
97
|
+
# and +:message+ can be given to one specific validator, as a hash:
|
98
|
+
#
|
99
|
+
# validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true
|
81
100
|
def validates(*attributes)
|
82
|
-
defaults = attributes.extract_options
|
101
|
+
defaults = attributes.extract_options!.dup
|
83
102
|
validations = defaults.slice!(*_validates_default_keys)
|
84
103
|
|
85
104
|
raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
|
86
105
|
raise ArgumentError, "You need to supply at least one validation" if validations.empty?
|
87
106
|
|
88
|
-
defaults
|
107
|
+
defaults[:attributes] = attributes
|
89
108
|
|
90
109
|
validations.each do |key, options|
|
110
|
+
next unless options
|
91
111
|
key = "#{key.to_s.camelize}Validator"
|
92
112
|
|
93
113
|
begin
|
@@ -100,12 +120,24 @@ module ActiveModel
|
|
100
120
|
end
|
101
121
|
end
|
102
122
|
|
103
|
-
# This method is used to define
|
104
|
-
#
|
123
|
+
# This method is used to define validations that cannot be corrected by end
|
124
|
+
# users and are considered exceptional. So each validator defined with bang
|
105
125
|
# or <tt>:strict</tt> option set to <tt>true</tt> will always raise
|
106
126
|
# <tt>ActiveModel::StrictValidationFailed</tt> instead of adding error
|
107
|
-
# when validation fails.
|
108
|
-
#
|
127
|
+
# when validation fails. See <tt>validates</tt> for more information about
|
128
|
+
# the validation itself.
|
129
|
+
#
|
130
|
+
# class Person
|
131
|
+
# include ActiveModel::Validations
|
132
|
+
#
|
133
|
+
# attr_accessor :name
|
134
|
+
# validates! :name, presence: true
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# person = Person.new
|
138
|
+
# person.name = ''
|
139
|
+
# person.valid?
|
140
|
+
# # => ActiveModel::StrictValidationFailed: Name can't be blank
|
109
141
|
def validates!(*attributes)
|
110
142
|
options = attributes.extract_options!
|
111
143
|
options[:strict] = true
|
@@ -116,11 +148,11 @@ module ActiveModel
|
|
116
148
|
|
117
149
|
# When creating custom validators, it might be useful to be able to specify
|
118
150
|
# additional default keys. This can be done by overwriting this method.
|
119
|
-
def _validates_default_keys
|
151
|
+
def _validates_default_keys # :nodoc:
|
120
152
|
[:if, :unless, :on, :allow_blank, :allow_nil , :strict]
|
121
153
|
end
|
122
154
|
|
123
|
-
def _parse_validates_options(options)
|
155
|
+
def _parse_validates_options(options) # :nodoc:
|
124
156
|
case options
|
125
157
|
when TrueClass
|
126
158
|
{}
|