activemodel 6.1.7.10 → 7.0.0.alpha1

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -224
  3. data/MIT-LICENSE +2 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_model/api.rb +99 -0
  6. data/lib/active_model/attribute.rb +4 -0
  7. data/lib/active_model/attribute_methods.rb +99 -52
  8. data/lib/active_model/attribute_set.rb +4 -1
  9. data/lib/active_model/attributes.rb +15 -12
  10. data/lib/active_model/callbacks.rb +1 -1
  11. data/lib/active_model/conversion.rb +2 -2
  12. data/lib/active_model/dirty.rb +5 -4
  13. data/lib/active_model/errors.rb +17 -3
  14. data/lib/active_model/gem_version.rb +4 -4
  15. data/lib/active_model/locale/en.yml +1 -0
  16. data/lib/active_model/model.rb +6 -59
  17. data/lib/active_model/naming.rb +15 -8
  18. data/lib/active_model/secure_password.rb +0 -1
  19. data/lib/active_model/serialization.rb +7 -2
  20. data/lib/active_model/translation.rb +1 -1
  21. data/lib/active_model/type/helpers/numeric.rb +9 -1
  22. data/lib/active_model/type/helpers/time_value.rb +2 -2
  23. data/lib/active_model/type/integer.rb +4 -1
  24. data/lib/active_model/type/registry.rb +8 -38
  25. data/lib/active_model/type/time.rb +1 -1
  26. data/lib/active_model/type.rb +6 -6
  27. data/lib/active_model/validations/absence.rb +1 -1
  28. data/lib/active_model/validations/clusivity.rb +1 -1
  29. data/lib/active_model/validations/comparability.rb +29 -0
  30. data/lib/active_model/validations/comparison.rb +82 -0
  31. data/lib/active_model/validations/confirmation.rb +4 -4
  32. data/lib/active_model/validations/numericality.rb +27 -20
  33. data/lib/active_model/validations.rb +4 -4
  34. data/lib/active_model/validator.rb +2 -2
  35. data/lib/active_model.rb +2 -1
  36. metadata +14 -12
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/validations/comparability"
4
+
5
+ module ActiveModel
6
+ module Validations
7
+ class ComparisonValidator < EachValidator # :nodoc:
8
+ include Comparability
9
+
10
+ def check_validity!
11
+ unless (options.keys & COMPARE_CHECKS.keys).any?
12
+ raise ArgumentError, "Expected one of :greater_than, :greater_than_or_equal_to, "\
13
+ ":equal_to, :less_than, :less_than_or_equal_to, or :other_than option to be supplied."
14
+ end
15
+ end
16
+
17
+ def validate_each(record, attr_name, value)
18
+ options.slice(*COMPARE_CHECKS.keys).each do |option, raw_option_value|
19
+ option_value = option_value(record, raw_option_value)
20
+
21
+ if value.nil? || value.blank?
22
+ return record.errors.add(attr_name, :blank, **error_options(value, option_value))
23
+ end
24
+
25
+ unless value.public_send(COMPARE_CHECKS[option], option_value)
26
+ record.errors.add(attr_name, option, **error_options(value, option_value))
27
+ end
28
+ rescue ArgumentError => e
29
+ record.errors.add(attr_name, e.message)
30
+ end
31
+ end
32
+ end
33
+
34
+ module HelperMethods
35
+ # Validates the value of a specified attribute fulfills all
36
+ # defined comparisons with another value, proc, or attribute.
37
+ #
38
+ # class Person < ActiveRecord::Base
39
+ # validates_comparison_of :value, greater_than: 'the sum of its parts'
40
+ # end
41
+ #
42
+ # Configuration options:
43
+ # * <tt>:message</tt> - A custom error message (default is: "failed comparison").
44
+ # * <tt>:greater_than</tt> - Specifies the value must be greater than the
45
+ # supplied value.
46
+ # * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be
47
+ # greater than or equal to the supplied value.
48
+ # * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied
49
+ # value.
50
+ # * <tt>:less_than</tt> - Specifies the value must be less than the
51
+ # supplied value.
52
+ # * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less
53
+ # than or equal to the supplied value.
54
+ # * <tt>:other_than</tt> - Specifies the value must not be equal to the
55
+ # supplied value.
56
+ #
57
+ # There is also a list of default options supported by every validator:
58
+ # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+ .
59
+ # See <tt>ActiveModel::Validations#validates</tt> for more information
60
+ #
61
+ # The validator requires at least one of the following checks to be supplied.
62
+ # Each will accept a proc, value, or a symbol which corresponds to a method:
63
+ #
64
+ # * <tt>:greater_than</tt>
65
+ # * <tt>:greater_than_or_equal_to</tt>
66
+ # * <tt>:equal_to</tt>
67
+ # * <tt>:less_than</tt>
68
+ # * <tt>:less_than_or_equal_to</tt>
69
+ # * <tt>:other_than</tt>
70
+ #
71
+ # For example:
72
+ #
73
+ # class Person < ActiveRecord::Base
74
+ # validates_comparison_of :birth_date, less_than_or_equal_to: -> { Date.today }
75
+ # validates_comparison_of :preferred_name, other_than: :given_name, allow_nil: true
76
+ # end
77
+ def validates_comparison_of(*attr_names)
78
+ validates_with ComparisonValidator, _merge_attributes(attr_names)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -19,13 +19,13 @@ module ActiveModel
19
19
 
20
20
  private
21
21
  def setup!(klass)
22
- klass.attr_reader(*attributes.map do |attribute|
22
+ klass.attr_reader(*attributes.filter_map do |attribute|
23
23
  :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
24
- end.compact)
24
+ end)
25
25
 
26
- klass.attr_writer(*attributes.map do |attribute|
26
+ klass.attr_writer(*attributes.filter_map do |attribute|
27
27
  :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=")
28
- end.compact)
28
+ end)
29
29
  end
30
30
 
31
31
  def confirmation_value_equal?(record, attribute, value, confirmed)
@@ -1,27 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_model/validations/comparability"
3
4
  require "bigdecimal/util"
4
5
 
5
6
  module ActiveModel
6
7
  module Validations
7
8
  class NumericalityValidator < EachValidator # :nodoc:
8
- CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=,
9
- equal_to: :==, less_than: :<, less_than_or_equal_to: :<=,
10
- odd: :odd?, even: :even?, other_than: :!= }.freeze
9
+ include Comparability
11
10
 
12
- RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
11
+ RANGE_CHECKS = { in: :in? }
12
+ NUMBER_CHECKS = { odd: :odd?, even: :even? }
13
+
14
+ RESERVED_OPTIONS = COMPARE_CHECKS.keys + NUMBER_CHECKS.keys + RANGE_CHECKS.keys + [:only_integer]
13
15
 
14
16
  INTEGER_REGEX = /\A[+-]?\d+\z/
15
17
 
16
18
  HEXADECIMAL_REGEX = /\A[+-]?0[xX]/
17
19
 
18
20
  def check_validity!
19
- keys = CHECKS.keys - [:odd, :even]
20
- options.slice(*keys).each do |option, value|
21
+ options.slice(*COMPARE_CHECKS.keys).each do |option, value|
21
22
  unless value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
22
23
  raise ArgumentError, ":#{option} must be a number, a symbol or a proc"
23
24
  end
24
25
  end
26
+
27
+ options.slice(*RANGE_CHECKS.keys).each do |option, value|
28
+ unless value.is_a?(Range)
29
+ raise ArgumentError, ":#{option} must be a range"
30
+ end
31
+ end
25
32
  end
26
33
 
27
34
  def validate_each(record, attr_name, value, precision: Float::DIG, scale: nil)
@@ -37,23 +44,18 @@ module ActiveModel
37
44
 
38
45
  value = parse_as_number(value, precision, scale)
39
46
 
40
- options.slice(*CHECKS.keys).each do |option, option_value|
41
- case option
42
- when :odd, :even
43
- unless value.to_i.public_send(CHECKS[option])
47
+ options.slice(*RESERVED_OPTIONS).each do |option, option_value|
48
+ if NUMBER_CHECKS.include?(option)
49
+ unless value.to_i.public_send(NUMBER_CHECKS[option])
44
50
  record.errors.add(attr_name, option, **filtered_options(value))
45
51
  end
46
- else
47
- case option_value
48
- when Proc
49
- option_value = option_value.call(record)
50
- when Symbol
51
- option_value = record.send(option_value)
52
+ elsif RANGE_CHECKS.include?(option)
53
+ unless value.public_send(RANGE_CHECKS[option], option_value)
54
+ record.errors.add(attr_name, option, **filtered_options(value).merge!(count: option_value))
52
55
  end
53
-
54
- option_value = parse_as_number(option_value, precision, scale)
55
-
56
- unless value.public_send(CHECKS[option], option_value)
56
+ elsif COMPARE_CHECKS.include?(option)
57
+ option_value = option_as_number(record, option_value, precision, scale)
58
+ unless value.public_send(COMPARE_CHECKS[option], option_value)
57
59
  record.errors.add(attr_name, option, **filtered_options(value).merge!(count: option_value))
58
60
  end
59
61
  end
@@ -61,6 +63,10 @@ module ActiveModel
61
63
  end
62
64
 
63
65
  private
66
+ def option_as_number(record, option_value, precision, scale)
67
+ parse_as_number(option_value(record, option_value), precision, scale)
68
+ end
69
+
64
70
  def parse_as_number(raw_value, precision, scale)
65
71
  if raw_value.is_a?(Float)
66
72
  parse_float(raw_value, precision, scale)
@@ -173,6 +179,7 @@ module ActiveModel
173
179
  # supplied value.
174
180
  # * <tt>:odd</tt> - Specifies the value must be an odd number.
175
181
  # * <tt>:even</tt> - Specifies the value must be an even number.
182
+ # * <tt>:in</tt> - Check that the value is within a range.
176
183
  #
177
184
  # There is also a list of default options supported by every validator:
178
185
  # +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+ .
@@ -118,7 +118,7 @@ module ActiveModel
118
118
  # end
119
119
  # end
120
120
  #
121
- # Or with a block where self points to the current record to be validated:
121
+ # Or with a block where +self+ points to the current record to be validated:
122
122
  #
123
123
  # class Comment
124
124
  # include ActiveModel::Validations
@@ -152,7 +152,7 @@ module ActiveModel
152
152
  def validate(*args, &block)
153
153
  options = args.extract_options!
154
154
 
155
- if args.all? { |arg| arg.is_a?(Symbol) }
155
+ if args.all?(Symbol)
156
156
  options.each_key do |k|
157
157
  unless VALID_OPTIONS_FOR_VALIDATE.include?(k)
158
158
  raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{VALID_OPTIONS_FOR_VALIDATE.map(&:inspect).join(', ')}. Perhaps you meant to call `validates` instead of `validate`?")
@@ -272,7 +272,7 @@ module ActiveModel
272
272
  end
273
273
 
274
274
  # Copy validators on inheritance.
275
- def inherited(base) #:nodoc:
275
+ def inherited(base) # :nodoc:
276
276
  dup = _validators.dup
277
277
  base._validators = dup.each { |k, v| dup[k] = v.dup }
278
278
  super
@@ -280,7 +280,7 @@ module ActiveModel
280
280
  end
281
281
 
282
282
  # Clean the +Errors+ object if instance is duped.
283
- def initialize_dup(other) #:nodoc:
283
+ def initialize_dup(other) # :nodoc:
284
284
  @errors = nil
285
285
  super
286
286
  end
@@ -129,7 +129,7 @@ module ActiveModel
129
129
  # record, attribute and value.
130
130
  #
131
131
  # All \Active \Model validations are built on top of this validator.
132
- class EachValidator < Validator #:nodoc:
132
+ class EachValidator < Validator
133
133
  attr_reader :attributes
134
134
 
135
135
  # Returns a new validator instance. All options will be available via the
@@ -174,7 +174,7 @@ module ActiveModel
174
174
 
175
175
  # +BlockValidator+ is a special +EachValidator+ which receives a block on initialization
176
176
  # and call this block for each attribute being validated. +validates_each+ uses this validator.
177
- class BlockValidator < EachValidator #:nodoc:
177
+ class BlockValidator < EachValidator # :nodoc:
178
178
  def initialize(options, &block)
179
179
  @block = block
180
180
  super
data/lib/active_model.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2022 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2021 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -30,6 +30,7 @@ require "active_model/version"
30
30
  module ActiveModel
31
31
  extend ActiveSupport::Autoload
32
32
 
33
+ autoload :API
33
34
  autoload :Attribute
34
35
  autoload :Attributes
35
36
  autoload :AttributeAssignment
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.7.10
4
+ version: 7.0.0.alpha1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-23 00:00:00.000000000 Z
11
+ date: 2021-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.1.7.10
19
+ version: 7.0.0.alpha1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.1.7.10
26
+ version: 7.0.0.alpha1
27
27
  description: A toolkit for building modeling frameworks like Active Record. Rich support
28
28
  for attributes, callbacks, validations, serialization, internationalization, and
29
29
  testing.
@@ -36,6 +36,7 @@ files:
36
36
  - MIT-LICENSE
37
37
  - README.rdoc
38
38
  - lib/active_model.rb
39
+ - lib/active_model/api.rb
39
40
  - lib/active_model/attribute.rb
40
41
  - lib/active_model/attribute/user_provided_default.rb
41
42
  - lib/active_model/attribute_assignment.rb
@@ -87,6 +88,8 @@ files:
87
88
  - lib/active_model/validations/acceptance.rb
88
89
  - lib/active_model/validations/callbacks.rb
89
90
  - lib/active_model/validations/clusivity.rb
91
+ - lib/active_model/validations/comparability.rb
92
+ - lib/active_model/validations/comparison.rb
90
93
  - lib/active_model/validations/confirmation.rb
91
94
  - lib/active_model/validations/exclusion.rb
92
95
  - lib/active_model/validations/format.rb
@@ -104,11 +107,10 @@ licenses:
104
107
  - MIT
105
108
  metadata:
106
109
  bug_tracker_uri: https://github.com/rails/rails/issues
107
- changelog_uri: https://github.com/rails/rails/blob/v6.1.7.10/activemodel/CHANGELOG.md
108
- documentation_uri: https://api.rubyonrails.org/v6.1.7.10/
110
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.0.alpha1/activemodel/CHANGELOG.md
111
+ documentation_uri: https://api.rubyonrails.org/v7.0.0.alpha1/
109
112
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
110
- source_code_uri: https://github.com/rails/rails/tree/v6.1.7.10/activemodel
111
- rubygems_mfa_required: 'true'
113
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.0.alpha1/activemodel
112
114
  post_install_message:
113
115
  rdoc_options: []
114
116
  require_paths:
@@ -117,14 +119,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
119
  requirements:
118
120
  - - ">="
119
121
  - !ruby/object:Gem::Version
120
- version: 2.5.0
122
+ version: 2.7.0
121
123
  required_rubygems_version: !ruby/object:Gem::Requirement
122
124
  requirements:
123
- - - ">="
125
+ - - ">"
124
126
  - !ruby/object:Gem::Version
125
- version: '0'
127
+ version: 1.3.1
126
128
  requirements: []
127
- rubygems_version: 3.5.16
129
+ rubygems_version: 3.1.6
128
130
  signing_key:
129
131
  specification_version: 4
130
132
  summary: A toolkit for building modeling frameworks (part of Rails).