activemodel 3.0.20 → 3.1.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.
- data/CHANGELOG +17 -73
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/lib/active_model.rb +2 -2
- data/lib/active_model/attribute_methods.rb +46 -53
- data/lib/active_model/callbacks.rb +2 -5
- data/lib/active_model/conversion.rb +0 -2
- data/lib/active_model/dirty.rb +3 -4
- data/lib/active_model/errors.rb +55 -56
- data/lib/active_model/lint.rb +2 -2
- data/lib/active_model/mass_assignment_security.rb +96 -47
- data/lib/active_model/naming.rb +55 -13
- data/lib/active_model/observer_array.rb +104 -0
- data/lib/active_model/observing.rb +53 -18
- data/lib/active_model/secure_password.rb +67 -0
- data/lib/active_model/serialization.rb +4 -11
- data/lib/active_model/serializers/json.rb +18 -18
- data/lib/active_model/serializers/xml.rb +26 -5
- data/lib/active_model/translation.rb +4 -11
- data/lib/active_model/validations.rb +23 -23
- data/lib/active_model/validations/acceptance.rb +3 -5
- data/lib/active_model/validations/callbacks.rb +5 -19
- data/lib/active_model/validations/confirmation.rb +6 -5
- data/lib/active_model/validations/exclusion.rb +27 -3
- data/lib/active_model/validations/format.rb +38 -12
- data/lib/active_model/validations/inclusion.rb +30 -23
- data/lib/active_model/validations/length.rb +3 -1
- data/lib/active_model/validations/numericality.rb +4 -2
- data/lib/active_model/validations/presence.rb +3 -2
- data/lib/active_model/validations/validates.rb +23 -9
- data/lib/active_model/validations/with.rb +14 -2
- data/lib/active_model/validator.rb +16 -18
- data/lib/active_model/version.rb +3 -3
- metadata +71 -58
- checksums.yaml +0 -7
- data/lib/active_model/deprecated_error_methods.rb +0 -33
@@ -18,12 +18,12 @@ module ActiveModel
|
|
18
18
|
#
|
19
19
|
# This also provides the required class methods for hooking into the
|
20
20
|
# Rails internationalization API, including being able to define a
|
21
|
-
# class based i18n_scope and lookup_ancestors to find translations in
|
21
|
+
# class based +i18n_scope+ and +lookup_ancestors+ to find translations in
|
22
22
|
# parent classes.
|
23
23
|
module Translation
|
24
24
|
include ActiveModel::Naming
|
25
25
|
|
26
|
-
# Returns the i18n_scope for the class. Overwrite if you want custom lookup.
|
26
|
+
# Returns the +i18n_scope+ for the class. Overwrite if you want custom lookup.
|
27
27
|
def i18n_scope
|
28
28
|
:activemodel
|
29
29
|
end
|
@@ -44,9 +44,8 @@ module ActiveModel
|
|
44
44
|
# Specify +options+ with additional translating options.
|
45
45
|
def human_attribute_name(attribute, options = {})
|
46
46
|
defaults = lookup_ancestors.map do |klass|
|
47
|
-
|
48
|
-
|
49
|
-
end.flatten
|
47
|
+
:"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}"
|
48
|
+
end
|
50
49
|
|
51
50
|
defaults << :"attributes.#{attribute}"
|
52
51
|
defaults << options.delete(:default) if options[:default]
|
@@ -55,11 +54,5 @@ module ActiveModel
|
|
55
54
|
options.reverse_merge! :count => 1, :default => defaults
|
56
55
|
I18n.translate(defaults.shift, options)
|
57
56
|
end
|
58
|
-
|
59
|
-
# Model.human_name is deprecated. Use Model.model_name.human instead.
|
60
|
-
def human_name(*args)
|
61
|
-
ActiveSupport::Deprecation.warn("human_name has been deprecated, please use model_name.human instead", caller[0,5])
|
62
|
-
model_name.human(*args)
|
63
|
-
end
|
64
57
|
end
|
65
58
|
end
|
@@ -36,8 +36,8 @@ module ActiveModel
|
|
36
36
|
# person.invalid? # => true
|
37
37
|
# person.errors # => #<OrderedHash {:first_name=>["starts with z."]}>
|
38
38
|
#
|
39
|
-
# Note that ActiveModel::Validations automatically adds an +errors+ method
|
40
|
-
# to your instances initialized with a new ActiveModel::Errors object, so
|
39
|
+
# Note that <tt>ActiveModel::Validations</tt> automatically adds an +errors+ method
|
40
|
+
# to your instances initialized with a new <tt>ActiveModel::Errors</tt> object, so
|
41
41
|
# there is no need for you to do this manually.
|
42
42
|
#
|
43
43
|
module Validations
|
@@ -71,8 +71,8 @@ module ActiveModel
|
|
71
71
|
# end
|
72
72
|
#
|
73
73
|
# Options:
|
74
|
-
# * <tt>:on</tt> - Specifies
|
75
|
-
# <tt>:
|
74
|
+
# * <tt>:on</tt> - Specifies the context where this validation is active
|
75
|
+
# (e.g. <tt>:on => :create</tt> or <tt>:on => :custom_validation_context</tt>)
|
76
76
|
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.
|
77
77
|
# * <tt>:allow_blank</tt> - Skip validation if attribute is blank.
|
78
78
|
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
|
@@ -104,7 +104,7 @@ module ActiveModel
|
|
104
104
|
# end
|
105
105
|
# end
|
106
106
|
#
|
107
|
-
#
|
107
|
+
# With a block which is passed with the current record to be validated:
|
108
108
|
#
|
109
109
|
# class Comment
|
110
110
|
# include ActiveModel::Validations
|
@@ -114,7 +114,17 @@ module ActiveModel
|
|
114
114
|
# end
|
115
115
|
#
|
116
116
|
# def must_be_friends
|
117
|
-
# errors.add(:base,
|
117
|
+
# errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee)
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# Or with a block where self points to the current record to be validated:
|
122
|
+
#
|
123
|
+
# class Comment
|
124
|
+
# include ActiveModel::Validations
|
125
|
+
#
|
126
|
+
# validate do
|
127
|
+
# errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee)
|
118
128
|
# end
|
119
129
|
# end
|
120
130
|
#
|
@@ -123,24 +133,12 @@ module ActiveModel
|
|
123
133
|
if options.key?(:on)
|
124
134
|
options = options.dup
|
125
135
|
options[:if] = Array.wrap(options[:if])
|
126
|
-
options[:if]
|
136
|
+
options[:if].unshift("validation_context == :#{options[:on]}")
|
127
137
|
end
|
128
138
|
args << options
|
129
139
|
set_callback(:validate, *args, &block)
|
130
140
|
end
|
131
141
|
|
132
|
-
[:create, :update].each do |type|
|
133
|
-
class_eval <<-RUBY
|
134
|
-
def validate_on_#{type}(*args, &block)
|
135
|
-
msg = "validate_on_#{type} is deprecated. Please use validate(args, :on => :#{type})"
|
136
|
-
ActiveSupport::Deprecation.warn(msg, caller)
|
137
|
-
options = args.extract_options!
|
138
|
-
options[:on] = :#{type}
|
139
|
-
validate(*args.push(options), &block)
|
140
|
-
end
|
141
|
-
RUBY
|
142
|
-
end
|
143
|
-
|
144
142
|
# List all validators that are being used to validate the model using
|
145
143
|
# +validates_with+ method.
|
146
144
|
def validators
|
@@ -148,8 +146,10 @@ module ActiveModel
|
|
148
146
|
end
|
149
147
|
|
150
148
|
# List all validators that being used to validate a specific attribute.
|
151
|
-
def validators_on(
|
152
|
-
|
149
|
+
def validators_on(*attributes)
|
150
|
+
attributes.map do |attribute|
|
151
|
+
_validators[attribute.to_sym]
|
152
|
+
end.flatten
|
153
153
|
end
|
154
154
|
|
155
155
|
# Check if method is an attribute method or not.
|
@@ -165,7 +165,7 @@ module ActiveModel
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
# Returns the Errors object that holds all information about attribute error messages.
|
168
|
+
# Returns the +Errors+ object that holds all information about attribute error messages.
|
169
169
|
def errors
|
170
170
|
@errors ||= Errors.new(self)
|
171
171
|
end
|
@@ -209,7 +209,7 @@ module ActiveModel
|
|
209
209
|
protected
|
210
210
|
|
211
211
|
def run_validations!
|
212
|
-
|
212
|
+
run_callbacks :validate
|
213
213
|
errors.empty?
|
214
214
|
end
|
215
215
|
end
|
@@ -14,8 +14,6 @@ module ActiveModel
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def setup(klass)
|
17
|
-
# Note: instance_methods.map(&:to_s) is important for 1.9 compatibility
|
18
|
-
# as instance_methods returns symbols unlike 1.8 which returns strings.
|
19
17
|
attr_readers = attributes.reject { |name| klass.attribute_method?(name) }
|
20
18
|
attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
|
21
19
|
klass.send(:attr_reader, *attr_readers)
|
@@ -39,9 +37,9 @@ module ActiveModel
|
|
39
37
|
# Configuration options:
|
40
38
|
# * <tt>:message</tt> - A custom error message (default is: "must be
|
41
39
|
# accepted").
|
42
|
-
# * <tt>:on</tt> - Specifies when this validation is active
|
43
|
-
#
|
44
|
-
# <tt>:update</tt
|
40
|
+
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
41
|
+
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
42
|
+
# and <tt>:update</tt>.
|
45
43
|
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default
|
46
44
|
# is true).
|
47
45
|
# * <tt>:accept</tt> - Specifies value that is considered accepted.
|
@@ -28,12 +28,12 @@ module ActiveModel
|
|
28
28
|
|
29
29
|
module ClassMethods
|
30
30
|
def before_validation(*args, &block)
|
31
|
-
options = args.
|
31
|
+
options = args.last
|
32
32
|
if options.is_a?(Hash) && options[:on]
|
33
33
|
options[:if] = Array.wrap(options[:if])
|
34
|
-
options[:if]
|
34
|
+
options[:if].unshift("self.validation_context == :#{options[:on]}")
|
35
35
|
end
|
36
|
-
set_callback(:validation, :before, *
|
36
|
+
set_callback(:validation, :before, *args, &block)
|
37
37
|
end
|
38
38
|
|
39
39
|
def after_validation(*args, &block)
|
@@ -41,30 +41,16 @@ module ActiveModel
|
|
41
41
|
options[:prepend] = true
|
42
42
|
options[:if] = Array.wrap(options[:if])
|
43
43
|
options[:if] << "!halted"
|
44
|
-
options[:if]
|
44
|
+
options[:if].unshift("self.validation_context == :#{options[:on]}") if options[:on]
|
45
45
|
set_callback(:validation, :after, *(args << options), &block)
|
46
46
|
end
|
47
|
-
|
48
|
-
[:before, :after].each do |type|
|
49
|
-
[:create, :update].each do |on|
|
50
|
-
class_eval <<-RUBY
|
51
|
-
def #{type}_validation_on_#{on}(*args, &block)
|
52
|
-
msg = "#{type}_validation_on_#{on} is deprecated. Please use #{type}_validation(arguments, :on => :#{on}"
|
53
|
-
ActiveSupport::Deprecation.warn(msg, caller)
|
54
|
-
options = args.extract_options!
|
55
|
-
options[:on] = :#{on}
|
56
|
-
before_validation(*args.push(options), &block)
|
57
|
-
end
|
58
|
-
RUBY
|
59
|
-
end
|
60
|
-
end
|
61
47
|
end
|
62
48
|
|
63
49
|
protected
|
64
50
|
|
65
51
|
# Overwrite run validations to include callbacks.
|
66
52
|
def run_validations!
|
67
|
-
|
53
|
+
run_callbacks(:validation) { super }
|
68
54
|
end
|
69
55
|
end
|
70
56
|
end
|
@@ -4,9 +4,9 @@ module ActiveModel
|
|
4
4
|
module Validations
|
5
5
|
class ConfirmationValidator < EachValidator
|
6
6
|
def validate_each(record, attribute, value)
|
7
|
-
confirmed = record.send(
|
8
|
-
|
9
|
-
|
7
|
+
if (confirmed = record.send("#{attribute}_confirmation")) && (value != confirmed)
|
8
|
+
record.errors.add(attribute, :confirmation, options)
|
9
|
+
end
|
10
10
|
end
|
11
11
|
|
12
12
|
def setup(klass)
|
@@ -45,8 +45,9 @@ module ActiveModel
|
|
45
45
|
# Configuration options:
|
46
46
|
# * <tt>:message</tt> - A custom error message (default is: "doesn't match
|
47
47
|
# confirmation").
|
48
|
-
# * <tt>:on</tt> - Specifies when this validation is active
|
49
|
-
#
|
48
|
+
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
49
|
+
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
50
|
+
# and <tt>:update</tt>.
|
50
51
|
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
|
51
52
|
# if the validation should occur (e.g. <tt>:if => :allow_validation</tt>,
|
52
53
|
# or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
|
@@ -1,18 +1,35 @@
|
|
1
|
+
require 'active_support/core_ext/range.rb'
|
2
|
+
|
1
3
|
module ActiveModel
|
2
4
|
|
3
5
|
# == Active Model Exclusion Validator
|
4
6
|
module Validations
|
5
7
|
class ExclusionValidator < EachValidator
|
8
|
+
ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
|
9
|
+
"and must be supplied as the :in option of the configuration hash"
|
10
|
+
|
6
11
|
def check_validity!
|
7
|
-
|
8
|
-
|
12
|
+
unless [:include?, :call].any? { |method| options[:in].respond_to?(method) }
|
13
|
+
raise ArgumentError, ERROR_MESSAGE
|
14
|
+
end
|
9
15
|
end
|
10
16
|
|
11
17
|
def validate_each(record, attribute, value)
|
12
|
-
|
18
|
+
delimiter = options[:in]
|
19
|
+
exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
|
20
|
+
if exclusions.send(inclusion_method(exclusions), value)
|
13
21
|
record.errors.add(attribute, :exclusion, options.except(:in).merge!(:value => value))
|
14
22
|
end
|
15
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible values in the
|
28
|
+
# range for equality, so it may be slow for large ranges. The new <tt>Range#cover?</tt>
|
29
|
+
# uses the previous logic of comparing a value with the range endpoints.
|
30
|
+
def inclusion_method(enumerable)
|
31
|
+
enumerable.is_a?(Range) ? :cover? : :include?
|
32
|
+
end
|
16
33
|
end
|
17
34
|
|
18
35
|
module HelperMethods
|
@@ -22,13 +39,20 @@ module ActiveModel
|
|
22
39
|
# validates_exclusion_of :username, :in => %w( admin superuser ), :message => "You don't belong here"
|
23
40
|
# validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60"
|
24
41
|
# validates_exclusion_of :format, :in => %w( mov avi ), :message => "extension %{value} is not allowed"
|
42
|
+
# validates_exclusion_of :password, :in => lambda { |p| [p.username, p.first_name] }, :message => "should not be the same as your username or first name"
|
25
43
|
# end
|
26
44
|
#
|
27
45
|
# Configuration options:
|
28
46
|
# * <tt>:in</tt> - An enumerable object of items that the value shouldn't be part of.
|
47
|
+
# This can be supplied as a proc or lambda which returns an enumerable. If the enumerable
|
48
|
+
# is a range the test is performed with <tt>Range#cover?</tt>
|
49
|
+
# (backported in Active Support for 1.8), otherwise with <tt>include?</tt>.
|
29
50
|
# * <tt>:message</tt> - Specifies a custom error message (default is: "is reserved").
|
30
51
|
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
|
31
52
|
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
|
53
|
+
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
54
|
+
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
55
|
+
# and <tt>:update</tt>.
|
32
56
|
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
|
33
57
|
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
|
34
58
|
# method, proc or string should return or evaluate to a true or false value.
|
@@ -4,10 +4,12 @@ module ActiveModel
|
|
4
4
|
module Validations
|
5
5
|
class FormatValidator < EachValidator
|
6
6
|
def validate_each(record, attribute, value)
|
7
|
-
if options[:with]
|
8
|
-
record
|
9
|
-
|
10
|
-
|
7
|
+
if options[:with]
|
8
|
+
regexp = option_call(record, :with)
|
9
|
+
record_error(record, attribute, :with, value) if value.to_s !~ regexp
|
10
|
+
elsif options[:without]
|
11
|
+
regexp = option_call(record, :without)
|
12
|
+
record_error(record, attribute, :without, value) if value.to_s =~ regexp
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
@@ -16,12 +18,25 @@ module ActiveModel
|
|
16
18
|
raise ArgumentError, "Either :with or :without must be supplied (but not both)"
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
check_options_validity(options, :with)
|
22
|
+
check_options_validity(options, :without)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
22
26
|
|
23
|
-
|
24
|
-
|
27
|
+
def option_call(record, name)
|
28
|
+
option = options[name]
|
29
|
+
option.respond_to?(:call) ? option.call(record) : option
|
30
|
+
end
|
31
|
+
|
32
|
+
def record_error(record, attribute, name, value)
|
33
|
+
record.errors.add(attribute, :invalid, options.except(name).merge!(:value => value))
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_options_validity(options, name)
|
37
|
+
option = options[name]
|
38
|
+
if option && !option.is_a?(Regexp) && !option.respond_to?(:call)
|
39
|
+
raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}"
|
25
40
|
end
|
26
41
|
end
|
27
42
|
end
|
@@ -40,18 +55,29 @@ module ActiveModel
|
|
40
55
|
# validates_format_of :email, :without => /NOSPAM/
|
41
56
|
# end
|
42
57
|
#
|
58
|
+
# You can also provide a proc or lambda which will determine the regular expression that will be used to validate the attribute
|
59
|
+
#
|
60
|
+
# class Person < ActiveRecord::Base
|
61
|
+
# # Admin can have number as a first letter in their screen name
|
62
|
+
# validates_format_of :screen_name, :with => lambda{ |person| person.admin? ? /\A[a-z0-9][a-z0-9_\-]*\Z/i : /\A[a-z][a-z0-9_\-]*\Z/i }
|
63
|
+
# end
|
64
|
+
#
|
43
65
|
# Note: use <tt>\A</tt> and <tt>\Z</tt> to match the start and end of the string, <tt>^</tt> and <tt>$</tt> match the start/end of a line.
|
44
66
|
#
|
45
|
-
# You must pass either <tt>:with</tt> or <tt>:without</tt> as an option. In addition, both must be a regular expression
|
46
|
-
# or else an exception will be raised.
|
67
|
+
# You must pass either <tt>:with</tt> or <tt>:without</tt> as an option. In addition, both must be a regular expression
|
68
|
+
# or a proc or lambda, or else an exception will be raised.
|
47
69
|
#
|
48
70
|
# Configuration options:
|
49
71
|
# * <tt>:message</tt> - A custom error message (default is: "is invalid").
|
50
72
|
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
|
51
73
|
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
|
52
74
|
# * <tt>:with</tt> - Regular expression that if the attribute matches will result in a successful validation.
|
75
|
+
# This can be provided as a proc or lambda returning regular expression which will be called at runtime.
|
53
76
|
# * <tt>:without</tt> - Regular expression that if the attribute does not match will result in a successful validation.
|
54
|
-
#
|
77
|
+
# This can be provided as a proc or lambda returning regular expression which will be called at runtime.
|
78
|
+
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
79
|
+
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
80
|
+
# and <tt>:update</tt>.
|
55
81
|
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
|
56
82
|
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
|
57
83
|
# method, proc or string should return or evaluate to a true or false value.
|
@@ -1,35 +1,35 @@
|
|
1
|
+
require 'active_support/core_ext/range.rb'
|
2
|
+
|
1
3
|
module ActiveModel
|
2
4
|
|
3
5
|
# == Active Model Inclusion Validator
|
4
6
|
module Validations
|
5
7
|
class InclusionValidator < EachValidator
|
8
|
+
ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " <<
|
9
|
+
"and must be supplied as the :in option of the configuration hash"
|
10
|
+
|
6
11
|
def check_validity!
|
7
|
-
|
8
|
-
|
12
|
+
unless [:include?, :call].any?{ |method| options[:in].respond_to?(method) }
|
13
|
+
raise ArgumentError, ERROR_MESSAGE
|
14
|
+
end
|
9
15
|
end
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
included = if options[:in].is_a?(Range)
|
17
|
-
options[:in].cover?(value)
|
18
|
-
else
|
19
|
-
options[:in].include?(value)
|
20
|
-
end
|
21
|
-
|
22
|
-
unless included
|
23
|
-
record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value))
|
24
|
-
end
|
25
|
-
end
|
26
|
-
else
|
27
|
-
def validate_each(record, attribute, value)
|
28
|
-
unless options[:in].include?(value)
|
29
|
-
record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value))
|
30
|
-
end
|
17
|
+
def validate_each(record, attribute, value)
|
18
|
+
delimiter = options[:in]
|
19
|
+
exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter
|
20
|
+
unless exclusions.send(inclusion_method(exclusions), value)
|
21
|
+
record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value))
|
31
22
|
end
|
32
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# In Ruby 1.9 <tt>Range#include?</tt> on non-numeric ranges checks all possible values in the
|
28
|
+
# range for equality, so it may be slow for large ranges. The new <tt>Range#cover?</tt>
|
29
|
+
# uses the previous logic of comparing a value with the range endpoints.
|
30
|
+
def inclusion_method(enumerable)
|
31
|
+
enumerable.is_a?(Range) ? :cover? : :include?
|
32
|
+
end
|
33
33
|
end
|
34
34
|
|
35
35
|
module HelperMethods
|
@@ -39,13 +39,20 @@ module ActiveModel
|
|
39
39
|
# validates_inclusion_of :gender, :in => %w( m f )
|
40
40
|
# validates_inclusion_of :age, :in => 0..99
|
41
41
|
# validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %{value} is not included in the list"
|
42
|
+
# validates_inclusion_of :states, :in => lambda{ |person| STATES[person.country] }
|
42
43
|
# end
|
43
44
|
#
|
44
45
|
# Configuration options:
|
45
|
-
# * <tt>:in</tt> - An enumerable object of available items.
|
46
|
+
# * <tt>:in</tt> - An enumerable object of available items. This can be
|
47
|
+
# supplied as a proc or lambda which returns an enumerable. If the enumerable
|
48
|
+
# is a range the test is performed with <tt>Range#cover?</tt>
|
49
|
+
# (backported in Active Support for 1.8), otherwise with <tt>include?</tt>.
|
46
50
|
# * <tt>:message</tt> - Specifies a custom error message (default is: "is not included in the list").
|
47
51
|
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
|
48
52
|
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
|
53
|
+
# * <tt>:on</tt> - Specifies when this validation is active. Runs in all
|
54
|
+
# validation contexts by default (+nil+), other options are <tt>:create</tt>
|
55
|
+
# and <tt>:update</tt>.
|
49
56
|
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
|
50
57
|
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
|
51
58
|
# method, proc or string should return or evaluate to a true or false value.
|