activemodel 5.0.7.2 → 5.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.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +15 -219
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_model.rb +11 -12
  6. data/lib/active_model/attribute_assignment.rb +11 -11
  7. data/lib/active_model/attribute_methods.rb +13 -15
  8. data/lib/active_model/callbacks.rb +19 -20
  9. data/lib/active_model/conversion.rb +12 -3
  10. data/lib/active_model/dirty.rb +14 -14
  11. data/lib/active_model/errors.rb +27 -103
  12. data/lib/active_model/forbidden_attributes_protection.rb +1 -1
  13. data/lib/active_model/gem_version.rb +3 -3
  14. data/lib/active_model/lint.rb +0 -1
  15. data/lib/active_model/model.rb +3 -4
  16. data/lib/active_model/naming.rb +9 -10
  17. data/lib/active_model/secure_password.rb +1 -1
  18. data/lib/active_model/serialization.rb +2 -2
  19. data/lib/active_model/serializers/json.rb +2 -2
  20. data/lib/active_model/translation.rb +2 -3
  21. data/lib/active_model/type.rb +15 -19
  22. data/lib/active_model/type/big_integer.rb +4 -4
  23. data/lib/active_model/type/binary.rb +1 -1
  24. data/lib/active_model/type/boolean.rb +20 -9
  25. data/lib/active_model/type/date.rb +25 -25
  26. data/lib/active_model/type/date_time.rb +21 -21
  27. data/lib/active_model/type/decimal.rb +35 -39
  28. data/lib/active_model/type/float.rb +17 -8
  29. data/lib/active_model/type/helpers.rb +4 -4
  30. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +2 -2
  31. data/lib/active_model/type/helpers/mutable.rb +2 -2
  32. data/lib/active_model/type/helpers/numeric.rb +18 -17
  33. data/lib/active_model/type/helpers/time_value.rb +23 -23
  34. data/lib/active_model/type/immutable_string.rb +9 -8
  35. data/lib/active_model/type/integer.rb +23 -21
  36. data/lib/active_model/type/registry.rb +12 -8
  37. data/lib/active_model/type/string.rb +1 -6
  38. data/lib/active_model/type/time.rb +15 -11
  39. data/lib/active_model/type/value.rb +6 -6
  40. data/lib/active_model/validations.rb +9 -12
  41. data/lib/active_model/validations/absence.rb +1 -1
  42. data/lib/active_model/validations/acceptance.rb +41 -40
  43. data/lib/active_model/validations/callbacks.rb +4 -7
  44. data/lib/active_model/validations/clusivity.rb +7 -7
  45. data/lib/active_model/validations/confirmation.rb +15 -16
  46. data/lib/active_model/validations/exclusion.rb +1 -2
  47. data/lib/active_model/validations/format.rb +24 -24
  48. data/lib/active_model/validations/inclusion.rb +1 -2
  49. data/lib/active_model/validations/length.rb +6 -42
  50. data/lib/active_model/validations/numericality.rb +3 -11
  51. data/lib/active_model/validations/presence.rb +1 -2
  52. data/lib/active_model/validations/validates.rb +6 -6
  53. data/lib/active_model/validations/with.rb +4 -2
  54. data/lib/active_model/validator.rb +5 -6
  55. data/lib/active_model/version.rb +1 -1
  56. metadata +8 -11
  57. data/lib/active_model/test_case.rb +0 -4
  58. data/lib/active_model/type/decimal_without_scale.rb +0 -11
  59. data/lib/active_model/type/text.rb +0 -11
  60. data/lib/active_model/type/unsigned_integer.rb +0 -15
@@ -23,14 +23,12 @@ module ActiveModel
23
23
  included do
24
24
  include ActiveSupport::Callbacks
25
25
  define_callbacks :validation,
26
- terminator: deprecated_false_terminator,
27
26
  skip_after_callbacks_if_terminated: true,
28
27
  scope: [:kind, :name]
29
28
  end
30
29
 
31
30
  module ClassMethods
32
- # Defines a callback that will get called right before validation
33
- # happens.
31
+ # Defines a callback that will get called right before validation.
34
32
  #
35
33
  # class Person
36
34
  # include ActiveModel::Validations
@@ -65,8 +63,7 @@ module ActiveModel
65
63
  set_callback(:validation, :before, *args, &block)
66
64
  end
67
65
 
68
- # Defines a callback that will get called right after validation
69
- # happens.
66
+ # Defines a callback that will get called right after validation.
70
67
  #
71
68
  # class Person
72
69
  # include ActiveModel::Validations
@@ -106,10 +103,10 @@ module ActiveModel
106
103
  end
107
104
  end
108
105
 
109
- protected
106
+ private
110
107
 
111
108
  # Overwrite run validations to include callbacks.
112
- def run_validations! #:nodoc:
109
+ def run_validations!
113
110
  _run_validation_callbacks { super }
114
111
  end
115
112
  end
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/range'
1
+ require "active_support/core_ext/range"
2
2
 
3
3
  module ActiveModel
4
4
  module Validations
@@ -16,12 +16,12 @@ module ActiveModel
16
16
 
17
17
  def include?(record, value)
18
18
  members = if delimiter.respond_to?(:call)
19
- delimiter.call(record)
20
- elsif delimiter.respond_to?(:to_sym)
21
- record.send(delimiter)
22
- else
23
- delimiter
24
- end
19
+ delimiter.call(record)
20
+ elsif delimiter.respond_to?(:to_sym)
21
+ record.send(delimiter)
22
+ else
23
+ delimiter
24
+ end
25
25
 
26
26
  members.send(inclusion_method(members), value)
27
27
  end
@@ -1,5 +1,4 @@
1
1
  module ActiveModel
2
-
3
2
  module Validations
4
3
  class ConfirmationValidator < EachValidator # :nodoc:
5
4
  def initialize(options)
@@ -17,23 +16,23 @@ module ActiveModel
17
16
  end
18
17
 
19
18
  private
20
- def setup!(klass)
21
- klass.send(:attr_reader, *attributes.map do |attribute|
22
- :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
23
- end.compact)
19
+ def setup!(klass)
20
+ klass.send(:attr_reader, *attributes.map do |attribute|
21
+ :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
22
+ end.compact)
24
23
 
25
- klass.send(:attr_writer, *attributes.map do |attribute|
26
- :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=")
27
- end.compact)
28
- end
24
+ klass.send(:attr_writer, *attributes.map do |attribute|
25
+ :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=")
26
+ end.compact)
27
+ end
29
28
 
30
- def confirmation_value_equal?(record, attribute, value, confirmed)
31
- if !options[:case_sensitive] && value.is_a?(String)
32
- value.casecmp(confirmed) == 0
33
- else
34
- value == confirmed
29
+ def confirmation_value_equal?(record, attribute, value, confirmed)
30
+ if !options[:case_sensitive] && value.is_a?(String)
31
+ value.casecmp(confirmed) == 0
32
+ else
33
+ value == confirmed
34
+ end
35
35
  end
36
- end
37
36
  end
38
37
 
39
38
  module HelperMethods
@@ -70,7 +69,7 @@ module ActiveModel
70
69
  #
71
70
  # There is also a list of default options supported by every validator:
72
71
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
73
- # See <tt>ActiveModel::Validation#validates</tt> for more information
72
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
74
73
  def validates_confirmation_of(*attr_names)
75
74
  validates_with ConfirmationValidator, _merge_attributes(attr_names)
76
75
  end
@@ -1,7 +1,6 @@
1
1
  require "active_model/validations/clusivity"
2
2
 
3
3
  module ActiveModel
4
-
5
4
  module Validations
6
5
  class ExclusionValidator < EachValidator # :nodoc:
7
6
  include Clusivity
@@ -39,7 +38,7 @@ module ActiveModel
39
38
  #
40
39
  # There is also a list of default options supported by every validator:
41
40
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
42
- # See <tt>ActiveModel::Validation#validates</tt> for more information
41
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
43
42
  def validates_exclusion_of(*attr_names)
44
43
  validates_with ExclusionValidator, _merge_attributes(attr_names)
45
44
  end
@@ -1,5 +1,5 @@
1
- module ActiveModel
2
1
 
2
+ module ActiveModel
3
3
  module Validations
4
4
  class FormatValidator < EachValidator # :nodoc:
5
5
  def validate_each(record, attribute, value)
@@ -8,7 +8,7 @@ module ActiveModel
8
8
  record_error(record, attribute, :with, value) if value.to_s !~ regexp
9
9
  elsif options[:without]
10
10
  regexp = option_call(record, :without)
11
- record_error(record, attribute, :without, value) if value.to_s =~ regexp
11
+ record_error(record, attribute, :without, value) if regexp.match?(value.to_s)
12
12
  end
13
13
  end
14
14
 
@@ -23,33 +23,33 @@ module ActiveModel
23
23
 
24
24
  private
25
25
 
26
- def option_call(record, name)
27
- option = options[name]
28
- option.respond_to?(:call) ? option.call(record) : option
29
- end
26
+ def option_call(record, name)
27
+ option = options[name]
28
+ option.respond_to?(:call) ? option.call(record) : option
29
+ end
30
30
 
31
- def record_error(record, attribute, name, value)
32
- record.errors.add(attribute, :invalid, options.except(name).merge!(value: value))
33
- end
31
+ def record_error(record, attribute, name, value)
32
+ record.errors.add(attribute, :invalid, options.except(name).merge!(value: value))
33
+ end
34
34
 
35
- def check_options_validity(name)
36
- if option = options[name]
37
- if option.is_a?(Regexp)
38
- if options[:multiline] != true && regexp_using_multiline_anchors?(option)
39
- raise ArgumentError, "The provided regular expression is using multiline anchors (^ or $), " \
40
- "which may present a security risk. Did you mean to use \\A and \\z, or forgot to add the " \
41
- ":multiline => true option?"
35
+ def check_options_validity(name)
36
+ if option = options[name]
37
+ if option.is_a?(Regexp)
38
+ if options[:multiline] != true && regexp_using_multiline_anchors?(option)
39
+ raise ArgumentError, "The provided regular expression is using multiline anchors (^ or $), " \
40
+ "which may present a security risk. Did you mean to use \\A and \\z, or forgot to add the " \
41
+ ":multiline => true option?"
42
+ end
43
+ elsif !option.respond_to?(:call)
44
+ raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}"
42
45
  end
43
- elsif !option.respond_to?(:call)
44
- raise ArgumentError, "A regular expression or a proc or lambda must be supplied as :#{name}"
45
46
  end
46
47
  end
47
- end
48
48
 
49
- def regexp_using_multiline_anchors?(regexp)
50
- source = regexp.source
51
- source.start_with?("^") || (source.end_with?("$") && !source.end_with?("\\$"))
52
- end
49
+ def regexp_using_multiline_anchors?(regexp)
50
+ source = regexp.source
51
+ source.start_with?("^") || (source.end_with?("$") && !source.end_with?("\\$"))
52
+ end
53
53
  end
54
54
 
55
55
  module HelperMethods
@@ -104,7 +104,7 @@ module ActiveModel
104
104
  #
105
105
  # There is also a list of default options supported by every validator:
106
106
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
107
- # See <tt>ActiveModel::Validation#validates</tt> for more information
107
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
108
108
  def validates_format_of(*attr_names)
109
109
  validates_with FormatValidator, _merge_attributes(attr_names)
110
110
  end
@@ -1,7 +1,6 @@
1
1
  require "active_model/validations/clusivity"
2
2
 
3
3
  module ActiveModel
4
-
5
4
  module Validations
6
5
  class InclusionValidator < EachValidator # :nodoc:
7
6
  include Clusivity
@@ -37,7 +36,7 @@ module ActiveModel
37
36
  #
38
37
  # There is also a list of default options supported by every validator:
39
38
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
40
- # See <tt>ActiveModel::Validation#validates</tt> for more information
39
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
41
40
  def validates_inclusion_of(*attr_names)
42
41
  validates_with InclusionValidator, _merge_attributes(attr_names)
43
42
  end
@@ -1,12 +1,10 @@
1
- require "active_support/core_ext/string/strip"
2
-
3
1
  module ActiveModel
4
2
  module Validations
5
3
  class LengthValidator < EachValidator # :nodoc:
6
4
  MESSAGES = { is: :wrong_length, minimum: :too_short, maximum: :too_long }.freeze
7
5
  CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze
8
6
 
9
- RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :tokenizer, :too_short, :too_long]
7
+ RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :too_short, :too_long]
10
8
 
11
9
  def initialize(options)
12
10
  if range = (options.delete(:in) || options.delete(:within))
@@ -18,27 +16,6 @@ module ActiveModel
18
16
  options[:minimum] = 1
19
17
  end
20
18
 
21
- if options[:tokenizer]
22
- ActiveSupport::Deprecation.warn(<<-EOS.strip_heredoc)
23
- The `:tokenizer` option is deprecated, and will be removed in Rails 5.1.
24
- You can achieve the same functionality by defining an instance method
25
- with the value that you want to validate the length of. For example,
26
-
27
- validates_length_of :essay, minimum: 100,
28
- tokenizer: ->(str) { str.scan(/\w+/) }
29
-
30
- should be written as
31
-
32
- validates_length_of :words_in_essay, minimum: 100
33
-
34
- private
35
-
36
- def words_in_essay
37
- essay.scan(/\w+/)
38
- end
39
- EOS
40
- end
41
-
42
19
  super
43
20
  end
44
21
 
@@ -46,7 +23,7 @@ module ActiveModel
46
23
  keys = CHECKS.keys & options.keys
47
24
 
48
25
  if keys.empty?
49
- raise ArgumentError, 'Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.'
26
+ raise ArgumentError, "Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option."
50
27
  end
51
28
 
52
29
  keys.each do |key|
@@ -59,7 +36,6 @@ module ActiveModel
59
36
  end
60
37
 
61
38
  def validate_each(record, attribute, value)
62
- value = tokenize(record, value)
63
39
  value_length = value.respond_to?(:length) ? value.length : value.to_s.length
64
40
  errors_options = options.except(*RESERVED_OPTIONS)
65
41
 
@@ -80,24 +56,12 @@ module ActiveModel
80
56
  end
81
57
 
82
58
  private
83
- def tokenize(record, value)
84
- tokenizer = options[:tokenizer]
85
- if tokenizer && value.kind_of?(String)
86
- if tokenizer.kind_of?(Proc)
87
- tokenizer.call(value)
88
- elsif record.respond_to?(tokenizer)
89
- record.send(tokenizer, value)
90
- end
91
- end || value
92
- end
93
-
94
- def skip_nil_check?(key)
95
- key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil?
96
- end
59
+ def skip_nil_check?(key)
60
+ key == :maximum && options[:allow_nil].nil? && options[:allow_blank].nil?
61
+ end
97
62
  end
98
63
 
99
64
  module HelperMethods
100
-
101
65
  # Validates that the specified attributes match the length restrictions
102
66
  # supplied. Only one constraint option can be used at a time apart from
103
67
  # +:minimum+ and +:maximum+ that can be combined together:
@@ -146,7 +110,7 @@ module ActiveModel
146
110
  #
147
111
  # There is also a list of default options supported by every validator:
148
112
  # +:if+, +:unless+, +:on+ and +:strict+.
149
- # See <tt>ActiveModel::Validation#validates</tt> for more information
113
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
150
114
  def validates_length_of(*attr_names)
151
115
  validates_with LengthValidator, _merge_attributes(attr_names)
152
116
  end
@@ -1,5 +1,4 @@
1
1
  module ActiveModel
2
-
3
2
  module Validations
4
3
  class NumericalityValidator < EachValidator # :nodoc:
5
4
  CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=,
@@ -27,8 +26,6 @@ module ActiveModel
27
26
  raw_value = value
28
27
  end
29
28
 
30
- return if options[:allow_nil] && raw_value.nil?
31
-
32
29
  unless is_number?(raw_value)
33
30
  record.errors.add(attr_name, :not_a_number, filtered_options(raw_value))
34
31
  return
@@ -39,9 +36,7 @@ module ActiveModel
39
36
  return
40
37
  end
41
38
 
42
- if raw_value.is_a?(Numeric)
43
- value = raw_value
44
- else
39
+ unless raw_value.is_a?(Numeric)
45
40
  value = parse_raw_value_as_a_number(raw_value)
46
41
  end
47
42
 
@@ -66,7 +61,7 @@ module ActiveModel
66
61
  end
67
62
  end
68
63
 
69
- protected
64
+ private
70
65
 
71
66
  def is_number?(raw_value)
72
67
  !parse_raw_value_as_a_number(raw_value).nil?
@@ -75,7 +70,6 @@ module ActiveModel
75
70
  end
76
71
 
77
72
  def parse_raw_value_as_a_number(raw_value)
78
- return raw_value.to_i if is_integer?(raw_value)
79
73
  Kernel.Float(raw_value) if raw_value !~ /\A0[xX]/
80
74
  end
81
75
 
@@ -100,8 +94,6 @@ module ActiveModel
100
94
  end
101
95
  end
102
96
 
103
- private
104
-
105
97
  def record_attribute_changed_in_place?(record, attr_name)
106
98
  record.respond_to?(:attribute_changed_in_place?) &&
107
99
  record.attribute_changed_in_place?(attr_name.to_s)
@@ -142,7 +134,7 @@ module ActiveModel
142
134
  #
143
135
  # There is also a list of default options supported by every validator:
144
136
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+ .
145
- # See <tt>ActiveModel::Validation#validates</tt> for more information
137
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
146
138
  #
147
139
  # The following checks can also be supplied with a proc or a symbol which
148
140
  # corresponds to a method:
@@ -1,6 +1,5 @@
1
1
 
2
2
  module ActiveModel
3
-
4
3
  module Validations
5
4
  class PresenceValidator < EachValidator # :nodoc:
6
5
  def validate_each(record, attr_name, value)
@@ -30,7 +29,7 @@ module ActiveModel
30
29
  #
31
30
  # There is also a list of default options supported by every validator:
32
31
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.
33
- # See <tt>ActiveModel::Validation#validates</tt> for more information
32
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
34
33
  def validates_presence_of(*attr_names)
35
34
  validates_with PresenceValidator, _merge_attributes(attr_names)
36
35
  end
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/hash/slice'
1
+ require "active_support/core_ext/hash/slice"
2
2
 
3
3
  module ActiveModel
4
4
  module Validations
@@ -72,7 +72,7 @@ module ActiveModel
72
72
  # There is also a list of options that could be used along with validators:
73
73
  #
74
74
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
75
- # Runs in all validation contexts by default (nil). You can pass a symbol
75
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
76
76
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
77
77
  # <tt>on: :custom_validation_context</tt> or
78
78
  # <tt>on: [:create, :custom_validation_context]</tt>)
@@ -115,7 +115,7 @@ module ActiveModel
115
115
  key = "#{key.to_s.camelize}Validator"
116
116
 
117
117
  begin
118
- validator = key.include?('::'.freeze) ? key.constantize : const_get(key)
118
+ validator = key.include?("::".freeze) ? key.constantize : const_get(key)
119
119
  rescue NameError
120
120
  raise ArgumentError, "Unknown validator: '#{key}'"
121
121
  end
@@ -148,15 +148,15 @@ module ActiveModel
148
148
  validates(*(attributes << options))
149
149
  end
150
150
 
151
- protected
151
+ private
152
152
 
153
153
  # When creating custom validators, it might be useful to be able to specify
154
154
  # additional default keys. This can be done by overwriting this method.
155
- def _validates_default_keys # :nodoc:
155
+ def _validates_default_keys
156
156
  [:if, :unless, :on, :allow_blank, :allow_nil , :strict]
157
157
  end
158
158
 
159
- def _parse_validates_options(options) # :nodoc:
159
+ def _parse_validates_options(options)
160
160
  case options
161
161
  when TrueClass
162
162
  {}
@@ -1,3 +1,5 @@
1
+ require "active_support/core_ext/array/extract_options"
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
  class WithValidator < EachValidator # :nodoc:
@@ -43,7 +45,7 @@ module ActiveModel
43
45
  #
44
46
  # Configuration options:
45
47
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
46
- # Runs in all validation contexts by default (nil). You can pass a symbol
48
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
47
49
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
48
50
  # <tt>on: :custom_validation_context</tt> or
49
51
  # <tt>on: [:create, :custom_validation_context]</tt>)
@@ -59,7 +61,7 @@ module ActiveModel
59
61
  # The method, proc or string should return or evaluate to a +true+ or
60
62
  # +false+ value.
61
63
  # * <tt>:strict</tt> - Specifies whether validation should be strict.
62
- # See <tt>ActiveModel::Validation#validates!</tt> for more information.
64
+ # See <tt>ActiveModel::Validations#validates!</tt> for more information.
63
65
  #
64
66
  # If you pass any additional configuration options, they will be passed
65
67
  # to the class and available as +options+: