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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -224
- data/MIT-LICENSE +2 -1
- data/README.rdoc +3 -3
- data/lib/active_model/api.rb +99 -0
- data/lib/active_model/attribute.rb +4 -0
- data/lib/active_model/attribute_methods.rb +99 -52
- data/lib/active_model/attribute_set.rb +4 -1
- data/lib/active_model/attributes.rb +15 -12
- data/lib/active_model/callbacks.rb +1 -1
- data/lib/active_model/conversion.rb +2 -2
- data/lib/active_model/dirty.rb +5 -4
- data/lib/active_model/errors.rb +17 -3
- data/lib/active_model/gem_version.rb +4 -4
- data/lib/active_model/locale/en.yml +1 -0
- data/lib/active_model/model.rb +6 -59
- data/lib/active_model/naming.rb +15 -8
- data/lib/active_model/secure_password.rb +0 -1
- data/lib/active_model/serialization.rb +7 -2
- data/lib/active_model/translation.rb +1 -1
- data/lib/active_model/type/helpers/numeric.rb +9 -1
- data/lib/active_model/type/helpers/time_value.rb +2 -2
- data/lib/active_model/type/integer.rb +4 -1
- data/lib/active_model/type/registry.rb +8 -38
- data/lib/active_model/type/time.rb +1 -1
- data/lib/active_model/type.rb +6 -6
- data/lib/active_model/validations/absence.rb +1 -1
- data/lib/active_model/validations/clusivity.rb +1 -1
- data/lib/active_model/validations/comparability.rb +29 -0
- data/lib/active_model/validations/comparison.rb +82 -0
- data/lib/active_model/validations/confirmation.rb +4 -4
- data/lib/active_model/validations/numericality.rb +27 -20
- data/lib/active_model/validations.rb +4 -4
- data/lib/active_model/validator.rb +2 -2
- data/lib/active_model.rb +2 -1
- 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.
|
22
|
+
klass.attr_reader(*attributes.filter_map do |attribute|
|
23
23
|
:"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
|
24
|
-
end
|
24
|
+
end)
|
25
25
|
|
26
|
-
klass.attr_writer(*attributes.
|
26
|
+
klass.attr_writer(*attributes.filter_map do |attribute|
|
27
27
|
:"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=")
|
28
|
-
end
|
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
|
-
|
9
|
-
equal_to: :==, less_than: :<, less_than_or_equal_to: :<=,
|
10
|
-
odd: :odd?, even: :even?, other_than: :!= }.freeze
|
9
|
+
include Comparability
|
11
10
|
|
12
|
-
|
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
|
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(*
|
41
|
-
|
42
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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 =
|
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?
|
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)
|
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)
|
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
|
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
|
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-
|
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:
|
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:
|
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:
|
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:
|
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/
|
108
|
-
documentation_uri: https://api.rubyonrails.org/
|
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/
|
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.
|
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:
|
127
|
+
version: 1.3.1
|
126
128
|
requirements: []
|
127
|
-
rubygems_version: 3.
|
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).
|