activemodel 3.0.20 → 3.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|