activemodel 5.2.4.1 → 6.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +115 -66
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -2
- data/lib/active_model.rb +1 -1
- data/lib/active_model/attribute.rb +3 -4
- data/lib/active_model/attribute/user_provided_default.rb +1 -2
- data/lib/active_model/attribute_assignment.rb +1 -1
- data/lib/active_model/attribute_methods.rb +54 -15
- data/lib/active_model/attribute_mutation_tracker.rb +88 -34
- data/lib/active_model/attribute_set.rb +2 -10
- data/lib/active_model/attribute_set/builder.rb +1 -3
- data/lib/active_model/attribute_set/yaml_encoder.rb +1 -2
- data/lib/active_model/attributes.rb +60 -33
- data/lib/active_model/callbacks.rb +10 -7
- data/lib/active_model/conversion.rb +1 -1
- data/lib/active_model/dirty.rb +36 -99
- data/lib/active_model/errors.rb +104 -20
- data/lib/active_model/gem_version.rb +4 -4
- data/lib/active_model/naming.rb +19 -3
- data/lib/active_model/railtie.rb +6 -0
- data/lib/active_model/secure_password.rb +47 -48
- data/lib/active_model/serializers/json.rb +10 -9
- data/lib/active_model/type/binary.rb +1 -1
- data/lib/active_model/type/date.rb +0 -4
- data/lib/active_model/type/date_time.rb +3 -7
- data/lib/active_model/type/float.rb +0 -2
- data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +4 -0
- data/lib/active_model/type/helpers/numeric.rb +9 -2
- data/lib/active_model/type/helpers/time_value.rb +17 -4
- data/lib/active_model/type/integer.rb +7 -19
- data/lib/active_model/type/registry.rb +2 -10
- data/lib/active_model/type/string.rb +2 -2
- data/lib/active_model/type/time.rb +1 -5
- data/lib/active_model/validations.rb +0 -2
- data/lib/active_model/validations/acceptance.rb +33 -25
- data/lib/active_model/validations/clusivity.rb +1 -1
- data/lib/active_model/validations/confirmation.rb +2 -2
- data/lib/active_model/validations/inclusion.rb +1 -1
- data/lib/active_model/validations/length.rb +1 -1
- data/lib/active_model/validations/numericality.rb +2 -2
- data/lib/active_model/validations/validates.rb +2 -2
- data/lib/active_model/validator.rb +1 -1
- metadata +11 -8
@@ -13,10 +13,6 @@ module ActiveModel
|
|
13
13
|
:datetime
|
14
14
|
end
|
15
15
|
|
16
|
-
def serialize(value)
|
17
|
-
super(cast(value))
|
18
|
-
end
|
19
|
-
|
20
16
|
private
|
21
17
|
|
22
18
|
def cast_value(value)
|
@@ -40,9 +36,9 @@ module ActiveModel
|
|
40
36
|
end
|
41
37
|
|
42
38
|
def value_from_multiparameter_assignment(values_hash)
|
43
|
-
|
44
|
-
if
|
45
|
-
raise ArgumentError,
|
39
|
+
missing_parameters = (1..3).select { |key| !values_hash.key?(key) }
|
40
|
+
if missing_parameters.any?
|
41
|
+
raise ArgumentError, "Provided hash #{values_hash} doesn't contain necessary keys: #{missing_parameters}"
|
46
42
|
end
|
47
43
|
super
|
48
44
|
end
|
@@ -5,6 +5,10 @@ module ActiveModel
|
|
5
5
|
module Helpers # :nodoc: all
|
6
6
|
class AcceptsMultiparameterTime < Module
|
7
7
|
def initialize(defaults: {})
|
8
|
+
define_method(:serialize) do |value|
|
9
|
+
super(cast(value))
|
10
|
+
end
|
11
|
+
|
8
12
|
define_method(:cast) do |value|
|
9
13
|
if value.is_a?(Hash)
|
10
14
|
value_from_multiparameter_assignment(value)
|
@@ -4,6 +4,10 @@ module ActiveModel
|
|
4
4
|
module Type
|
5
5
|
module Helpers # :nodoc: all
|
6
6
|
module Numeric
|
7
|
+
def serialize(value)
|
8
|
+
cast(value)
|
9
|
+
end
|
10
|
+
|
7
11
|
def cast(value)
|
8
12
|
value = \
|
9
13
|
case value
|
@@ -22,15 +26,18 @@ module ActiveModel
|
|
22
26
|
private
|
23
27
|
|
24
28
|
def number_to_non_number?(old_value, new_value_before_type_cast)
|
25
|
-
old_value != nil && non_numeric_string?(new_value_before_type_cast)
|
29
|
+
old_value != nil && non_numeric_string?(new_value_before_type_cast.to_s)
|
26
30
|
end
|
27
31
|
|
28
32
|
def non_numeric_string?(value)
|
29
33
|
# 'wibble'.to_i will give zero, we want to make sure
|
30
34
|
# that we aren't marking int zero to string zero as
|
31
35
|
# changed.
|
32
|
-
|
36
|
+
!NUMERIC_REGEX.match?(value)
|
33
37
|
end
|
38
|
+
|
39
|
+
NUMERIC_REGEX = /\A\s*[+-]?\d/
|
40
|
+
private_constant :NUMERIC_REGEX
|
34
41
|
end
|
35
42
|
end
|
36
43
|
end
|
@@ -22,10 +22,17 @@ module ActiveModel
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def apply_seconds_precision(value)
|
25
|
-
return value unless precision && value.respond_to?(:
|
26
|
-
|
25
|
+
return value unless precision && value.respond_to?(:nsec)
|
26
|
+
|
27
|
+
number_of_insignificant_digits = 9 - precision
|
27
28
|
round_power = 10**number_of_insignificant_digits
|
28
|
-
|
29
|
+
rounded_off_nsec = value.nsec % round_power
|
30
|
+
|
31
|
+
if rounded_off_nsec > 0
|
32
|
+
value.change(nsec: value.nsec - rounded_off_nsec)
|
33
|
+
else
|
34
|
+
value
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
38
|
def type_cast_for_schema(value)
|
@@ -58,7 +65,13 @@ module ActiveModel
|
|
58
65
|
# Doesn't handle time zones.
|
59
66
|
def fast_string_to_time(string)
|
60
67
|
if string =~ ISO_DATETIME
|
61
|
-
|
68
|
+
microsec_part = $7
|
69
|
+
if microsec_part && microsec_part.start_with?(".") && microsec_part.length == 7
|
70
|
+
microsec_part[0] = ""
|
71
|
+
microsec = microsec_part.to_i
|
72
|
+
else
|
73
|
+
microsec = (microsec_part.to_r * 1_000_000).to_i
|
74
|
+
end
|
62
75
|
new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
|
63
76
|
end
|
64
77
|
end
|
@@ -19,39 +19,27 @@ module ActiveModel
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def deserialize(value)
|
22
|
-
return if value.
|
22
|
+
return if value.blank?
|
23
23
|
value.to_i
|
24
24
|
end
|
25
25
|
|
26
26
|
def serialize(value)
|
27
|
-
|
28
|
-
|
29
|
-
ensure_in_range(result)
|
30
|
-
end
|
31
|
-
result
|
27
|
+
return if value.is_a?(::String) && non_numeric_string?(value)
|
28
|
+
ensure_in_range(super)
|
32
29
|
end
|
33
30
|
|
34
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
35
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
36
|
-
protected
|
37
|
-
|
38
|
-
attr_reader :range
|
39
|
-
|
40
31
|
private
|
32
|
+
attr_reader :range
|
41
33
|
|
42
34
|
def cast_value(value)
|
43
|
-
|
44
|
-
when true then 1
|
45
|
-
when false then 0
|
46
|
-
else
|
47
|
-
value.to_i rescue nil
|
48
|
-
end
|
35
|
+
value.to_i rescue nil
|
49
36
|
end
|
50
37
|
|
51
38
|
def ensure_in_range(value)
|
52
|
-
|
39
|
+
if value && !range.cover?(value)
|
53
40
|
raise ActiveModel::RangeError, "#{value} is out of range for #{self.class} with limit #{_limit} bytes"
|
54
41
|
end
|
42
|
+
value
|
55
43
|
end
|
56
44
|
|
57
45
|
def max_value
|
@@ -23,13 +23,8 @@ module ActiveModel
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
27
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
28
|
-
protected
|
29
|
-
|
30
|
-
attr_reader :registrations
|
31
|
-
|
32
26
|
private
|
27
|
+
attr_reader :registrations
|
33
28
|
|
34
29
|
def registration_klass
|
35
30
|
Registration
|
@@ -59,10 +54,7 @@ module ActiveModel
|
|
59
54
|
type_name == name
|
60
55
|
end
|
61
56
|
|
62
|
-
|
63
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
64
|
-
protected
|
65
|
-
|
57
|
+
private
|
66
58
|
attr_reader :name, :block
|
67
59
|
end
|
68
60
|
end
|
@@ -6,17 +6,13 @@ module ActiveModel
|
|
6
6
|
include Helpers::Timezone
|
7
7
|
include Helpers::TimeValue
|
8
8
|
include Helpers::AcceptsMultiparameterTime.new(
|
9
|
-
defaults: { 1 =>
|
9
|
+
defaults: { 1 => 2000, 2 => 1, 3 => 1, 4 => 0, 5 => 0 }
|
10
10
|
)
|
11
11
|
|
12
12
|
def type
|
13
13
|
:time
|
14
14
|
end
|
15
15
|
|
16
|
-
def serialize(value)
|
17
|
-
super(cast(value))
|
18
|
-
end
|
19
|
-
|
20
16
|
def user_input_in_time_zone(value)
|
21
17
|
return unless value.present?
|
22
18
|
|
@@ -17,7 +17,8 @@ module ActiveModel
|
|
17
17
|
private
|
18
18
|
|
19
19
|
def setup!(klass)
|
20
|
-
|
20
|
+
define_attributes = LazilyDefineAttributes.new(attributes)
|
21
|
+
klass.include(define_attributes) unless klass.included_modules.include?(define_attributes)
|
21
22
|
end
|
22
23
|
|
23
24
|
def acceptable_option?(value)
|
@@ -25,50 +26,57 @@ module ActiveModel
|
|
25
26
|
end
|
26
27
|
|
27
28
|
class LazilyDefineAttributes < Module
|
28
|
-
def initialize(
|
29
|
+
def initialize(attributes)
|
30
|
+
@attributes = attributes.map(&:to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
def included(klass)
|
34
|
+
@lock = Mutex.new
|
35
|
+
mod = self
|
36
|
+
|
29
37
|
define_method(:respond_to_missing?) do |method_name, include_private = false|
|
30
|
-
|
38
|
+
mod.define_on(klass)
|
39
|
+
super(method_name, include_private) || mod.matches?(method_name)
|
31
40
|
end
|
32
41
|
|
33
42
|
define_method(:method_missing) do |method_name, *args, &block|
|
34
|
-
|
35
|
-
|
43
|
+
mod.define_on(klass)
|
44
|
+
if mod.matches?(method_name)
|
36
45
|
send(method_name, *args, &block)
|
37
46
|
else
|
38
47
|
super(method_name, *args, &block)
|
39
48
|
end
|
40
49
|
end
|
41
50
|
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class AttributeDefinition
|
45
|
-
def initialize(attributes)
|
46
|
-
@attributes = attributes.map(&:to_s)
|
47
|
-
end
|
48
51
|
|
49
52
|
def matches?(method_name)
|
50
|
-
attr_name =
|
51
|
-
attributes.
|
53
|
+
attr_name = method_name.to_s.chomp("=")
|
54
|
+
attributes.any? { |name| name == attr_name }
|
52
55
|
end
|
53
56
|
|
54
57
|
def define_on(klass)
|
55
|
-
|
56
|
-
|
57
|
-
klass.send(:attr_reader, *attr_readers)
|
58
|
-
klass.send(:attr_writer, *attr_writers)
|
59
|
-
end
|
58
|
+
@lock&.synchronize do
|
59
|
+
return unless @lock
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
protected
|
61
|
+
attr_readers = attributes.reject { |name| klass.attribute_method?(name) }
|
62
|
+
attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
|
64
63
|
|
65
|
-
|
64
|
+
attr_reader(*attr_readers)
|
65
|
+
attr_writer(*attr_writers)
|
66
66
|
|
67
|
-
|
67
|
+
remove_method :respond_to_missing?
|
68
|
+
remove_method :method_missing
|
68
69
|
|
69
|
-
|
70
|
-
method_name.to_s.chomp("=")
|
70
|
+
@lock = nil
|
71
71
|
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def ==(other)
|
75
|
+
self.class == other.class && attributes == other.attributes
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
attr_reader :attributes
|
72
80
|
end
|
73
81
|
end
|
74
82
|
|
@@ -32,7 +32,7 @@ module ActiveModel
|
|
32
32
|
@delimiter ||= options[:in] || options[:within]
|
33
33
|
end
|
34
34
|
|
35
|
-
#
|
35
|
+
# After Ruby 2.2, <tt>Range#include?</tt> on non-number-or-time-ish ranges checks all
|
36
36
|
# possible values in the range for equality, which is slower but more accurate.
|
37
37
|
# <tt>Range#cover?</tt> uses the previous logic of comparing a value with the range
|
38
38
|
# endpoints, which is fast but is only accurate on Numeric, Time, Date,
|
@@ -19,11 +19,11 @@ module ActiveModel
|
|
19
19
|
|
20
20
|
private
|
21
21
|
def setup!(klass)
|
22
|
-
klass.
|
22
|
+
klass.attr_reader(*attributes.map do |attribute|
|
23
23
|
:"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
|
24
24
|
end.compact)
|
25
25
|
|
26
|
-
klass.
|
26
|
+
klass.attr_writer(*attributes.map do |attribute|
|
27
27
|
:"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=")
|
28
28
|
end.compact)
|
29
29
|
end
|
@@ -19,7 +19,7 @@ module ActiveModel
|
|
19
19
|
# particular enumerable object.
|
20
20
|
#
|
21
21
|
# class Person < ActiveRecord::Base
|
22
|
-
# validates_inclusion_of :
|
22
|
+
# validates_inclusion_of :role, in: %w( admin contributor )
|
23
23
|
# validates_inclusion_of :age, in: 0..99
|
24
24
|
# validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list"
|
25
25
|
# validates_inclusion_of :states, in: ->(person) { STATES[person.country] }
|
@@ -32,7 +32,7 @@ module ActiveModel
|
|
32
32
|
value = options[key]
|
33
33
|
|
34
34
|
unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY || value.is_a?(Symbol) || value.is_a?(Proc)
|
35
|
-
raise ArgumentError, ":#{key} must be a
|
35
|
+
raise ArgumentError, ":#{key} must be a non-negative Integer, Infinity, Symbol, or Proc"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -99,11 +99,11 @@ module ActiveModel
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def is_integer?(raw_value)
|
102
|
-
INTEGER_REGEX
|
102
|
+
INTEGER_REGEX.match?(raw_value.to_s)
|
103
103
|
end
|
104
104
|
|
105
105
|
def is_hexadecimal_literal?(raw_value)
|
106
|
-
/\A0[xX]
|
106
|
+
/\A0[xX]/.match?(raw_value.to_s)
|
107
107
|
end
|
108
108
|
|
109
109
|
def filtered_options(value)
|
@@ -63,7 +63,7 @@ module ActiveModel
|
|
63
63
|
# and strings in shortcut form.
|
64
64
|
#
|
65
65
|
# validates :email, format: /@/
|
66
|
-
# validates :
|
66
|
+
# validates :role, inclusion: %(admin contributor)
|
67
67
|
# validates :password, length: 6..20
|
68
68
|
#
|
69
69
|
# When using shortcut form, ranges and arrays are passed to your
|
@@ -116,7 +116,7 @@ module ActiveModel
|
|
116
116
|
key = "#{key.to_s.camelize}Validator"
|
117
117
|
|
118
118
|
begin
|
119
|
-
validator = key.include?("::"
|
119
|
+
validator = key.include?("::") ? key.constantize : const_get(key)
|
120
120
|
rescue NameError
|
121
121
|
raise ArgumentError, "Unknown validator: '#{key}'"
|
122
122
|
end
|
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: 6.0.1
|
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: 2019-
|
11
|
+
date: 2019-11-05 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: 6.0.1
|
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: 6.0.1
|
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.
|
@@ -97,12 +97,15 @@ files:
|
|
97
97
|
- lib/active_model/validations/with.rb
|
98
98
|
- lib/active_model/validator.rb
|
99
99
|
- lib/active_model/version.rb
|
100
|
-
homepage:
|
100
|
+
homepage: https://rubyonrails.org
|
101
101
|
licenses:
|
102
102
|
- MIT
|
103
103
|
metadata:
|
104
|
-
|
105
|
-
changelog_uri: https://github.com/rails/rails/blob/
|
104
|
+
bug_tracker_uri: https://github.com/rails/rails/issues
|
105
|
+
changelog_uri: https://github.com/rails/rails/blob/v6.0.1/activemodel/CHANGELOG.md
|
106
|
+
documentation_uri: https://api.rubyonrails.org/v6.0.1/
|
107
|
+
mailing_list_uri: https://groups.google.com/forum/#!forum/rubyonrails-talk
|
108
|
+
source_code_uri: https://github.com/rails/rails/tree/v6.0.1/activemodel
|
106
109
|
post_install_message:
|
107
110
|
rdoc_options: []
|
108
111
|
require_paths:
|
@@ -111,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
114
|
requirements:
|
112
115
|
- - ">="
|
113
116
|
- !ruby/object:Gem::Version
|
114
|
-
version: 2.
|
117
|
+
version: 2.5.0
|
115
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
119
|
requirements:
|
117
120
|
- - ">="
|