activemodel 5.2.2.1 → 6.0.2
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 +144 -51
- 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 +3 -3
- 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/boolean.rb +10 -1
- data/lib/active_model/type/date.rb +2 -5
- data/lib/active_model/type/date_time.rb +4 -7
- data/lib/active_model/type/float.rb +0 -2
- data/lib/active_model/type/helpers.rb +1 -0
- 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 +16 -15
- data/lib/active_model/type/helpers/timezone.rb +19 -0
- 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 +2 -1
- 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 +20 -11
- data/lib/active_model/validations/validates.rb +2 -2
- data/lib/active_model/validator.rb +1 -1
- metadata +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b4ec615d86d242d3390a1858b16660a3181a207cecce4c682dbc64e718b8e9e
|
4
|
+
data.tar.gz: a16653cb0dfa84234d586b236af2d7000fd0a12bb8c7367e072ee4951434b647
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee86c00af65340604a36f42ade73812752220d56834195e4103c302058ca45e98b6e62a7411f2d5681bb599a05190dd1fe7a385bc47bac638e9b719e2580f39b
|
7
|
+
data.tar.gz: 2a6d79cc1551bb3e6b168f51f6bdc05ff362edcf292f78178df558717c7a27358cb32c65207ad74cc140e140bae80d8cdf526e2902c46f5f8f63af1735adea23
|
data/CHANGELOG.md
CHANGED
@@ -1,89 +1,182 @@
|
|
1
|
-
## Rails
|
1
|
+
## Rails 6.0.2 (December 13, 2019) ##
|
2
2
|
|
3
3
|
* No changes.
|
4
4
|
|
5
5
|
|
6
|
-
## Rails
|
6
|
+
## Rails 6.0.1 (November 5, 2019) ##
|
7
7
|
|
8
|
-
*
|
8
|
+
* No changes.
|
9
9
|
|
10
|
-
Fixes #33651, #33686.
|
11
10
|
|
12
|
-
|
11
|
+
## Rails 6.0.0 (August 16, 2019) ##
|
12
|
+
|
13
|
+
* No changes.
|
13
14
|
|
14
15
|
|
15
|
-
## Rails
|
16
|
+
## Rails 6.0.0.rc2 (July 22, 2019) ##
|
16
17
|
|
17
18
|
* No changes.
|
18
19
|
|
19
20
|
|
20
|
-
## Rails
|
21
|
+
## Rails 6.0.0.rc1 (April 24, 2019) ##
|
22
|
+
|
23
|
+
* Type cast falsy boolean symbols on boolean attribute as false.
|
24
|
+
|
25
|
+
Fixes #35676.
|
26
|
+
|
27
|
+
*Ryuta Kamizono*
|
28
|
+
|
29
|
+
* Change how validation error translation strings are fetched: The new behavior
|
30
|
+
will first try the more specific keys, including doing locale fallback, then try
|
31
|
+
the less specific ones.
|
32
|
+
|
33
|
+
For example, this is the order in which keys will now be tried for a `blank`
|
34
|
+
error on a `product`'s `title` attribute with current locale set to `en-US`:
|
35
|
+
|
36
|
+
en-US.activerecord.errors.models.product.attributes.title.blank
|
37
|
+
en-US.activerecord.errors.models.product.blank
|
38
|
+
en-US.activerecord.errors.messages.blank
|
39
|
+
|
40
|
+
en.activerecord.errors.models.product.attributes.title.blank
|
41
|
+
en.activerecord.errors.models.product.blank
|
42
|
+
en.activerecord.errors.messages.blank
|
43
|
+
|
44
|
+
en-US.errors.attributes.title.blank
|
45
|
+
en-US.errors.messages.blank
|
46
|
+
|
47
|
+
en.errors.attributes.title.blank
|
48
|
+
en.errors.messages.blank
|
49
|
+
|
50
|
+
*Hugo Vacher*
|
51
|
+
|
52
|
+
|
53
|
+
## Rails 6.0.0.beta3 (March 11, 2019) ##
|
21
54
|
|
22
55
|
* No changes.
|
23
56
|
|
24
57
|
|
25
|
-
## Rails
|
58
|
+
## Rails 6.0.0.beta2 (February 25, 2019) ##
|
59
|
+
|
60
|
+
* Fix date value when casting a multiparameter date hash to not convert
|
61
|
+
from Gregorian date to Julian date.
|
62
|
+
|
63
|
+
Before:
|
64
|
+
|
65
|
+
Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
|
66
|
+
# => #<Day id: nil, day: "0001-01-03", created_at: nil, updated_at: nil>
|
26
67
|
|
27
|
-
|
68
|
+
After:
|
28
69
|
|
29
|
-
|
70
|
+
Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
|
71
|
+
# => #<Day id: nil, day: "0001-01-01", created_at: nil, updated_at: nil>
|
30
72
|
|
31
|
-
|
73
|
+
Fixes #28521.
|
32
74
|
|
33
|
-
|
75
|
+
*Sayan Chakraborty*
|
34
76
|
|
35
|
-
|
77
|
+
* Fix year value when casting a multiparameter time hash.
|
36
78
|
|
37
|
-
|
79
|
+
When assigning a hash to a time attribute that's missing a year component
|
80
|
+
(e.g. a `time_select` with `:ignore_date` set to `true`) then the year
|
81
|
+
defaults to 1970 instead of the expected 2000. This results in the attribute
|
82
|
+
changing as a result of the save.
|
38
83
|
|
39
|
-
|
84
|
+
Before:
|
85
|
+
```
|
86
|
+
event = Event.new(start_time: { 4 => 20, 5 => 30 })
|
87
|
+
event.start_time # => 1970-01-01 20:30:00 UTC
|
88
|
+
event.save
|
89
|
+
event.reload
|
90
|
+
event.start_time # => 2000-01-01 20:30:00 UTC
|
91
|
+
```
|
40
92
|
|
41
|
-
|
93
|
+
After:
|
94
|
+
```
|
95
|
+
event = Event.new(start_time: { 4 => 20, 5 => 30 })
|
96
|
+
event.start_time # => 2000-01-01 20:30:00 UTC
|
97
|
+
event.save
|
98
|
+
event.reload
|
99
|
+
event.start_time # => 2000-01-01 20:30:00 UTC
|
100
|
+
```
|
42
101
|
|
43
|
-
*
|
102
|
+
*Andrew White*
|
44
103
|
|
45
|
-
* Allow passing a Proc or Symbol to length validator options.
|
46
104
|
|
47
|
-
|
105
|
+
## Rails 6.0.0.beta1 (January 18, 2019) ##
|
48
106
|
|
49
|
-
*
|
107
|
+
* Internal calls to `human_attribute_name` on an `Active Model` now pass attributes as strings instead of symbols
|
108
|
+
in some cases.
|
50
109
|
|
51
|
-
|
110
|
+
This is in line with examples in Rails docs and puts the code in line with the intention -
|
111
|
+
the potential use of strings or symbols.
|
52
112
|
|
53
|
-
|
54
|
-
values with more scale than the schema.
|
113
|
+
It is recommended to cast the attribute input to your desired type as if you you are overriding that methid.
|
55
114
|
|
56
|
-
*
|
115
|
+
*Martin Larochelle*
|
57
116
|
|
58
|
-
*
|
117
|
+
* Add `ActiveModel::Errors#of_kind?`.
|
59
118
|
|
60
|
-
|
119
|
+
*bogdanvlviv*, *Rafael Mendonça França*
|
61
120
|
|
62
|
-
|
121
|
+
* Fix numericality equality validation of `BigDecimal` and `Float`
|
122
|
+
by casting to `BigDecimal` on both ends of the validation.
|
123
|
+
|
124
|
+
*Gannon McGibbon*
|
125
|
+
|
126
|
+
* Add `#slice!` method to `ActiveModel::Errors`.
|
127
|
+
|
128
|
+
*Daniel López Prat*
|
129
|
+
|
130
|
+
* Fix numericality validator to still use value before type cast except Active Record.
|
131
|
+
|
132
|
+
Fixes #33651, #33686.
|
133
|
+
|
134
|
+
*Ryuta Kamizono*
|
135
|
+
|
136
|
+
* Fix `ActiveModel::Serializers::JSON#as_json` method for timestamps.
|
137
|
+
|
138
|
+
Before:
|
139
|
+
```
|
140
|
+
contact = Contact.new(created_at: Time.utc(2006, 8, 1))
|
141
|
+
contact.as_json["created_at"] # => 2006-08-01 00:00:00 UTC
|
142
|
+
```
|
143
|
+
|
144
|
+
After:
|
145
|
+
```
|
146
|
+
contact = Contact.new(created_at: Time.utc(2006, 8, 1))
|
147
|
+
contact.as_json["created_at"] # => "2006-08-01T00:00:00.000Z"
|
148
|
+
```
|
149
|
+
|
150
|
+
*Bogdan Gusiev*
|
151
|
+
|
152
|
+
* Allows configurable attribute name for `#has_secure_password`. This
|
153
|
+
still defaults to an attribute named 'password', causing no breaking
|
154
|
+
change. There is a new method `#authenticate_XXX` where XXX is the
|
155
|
+
configured attribute name, making the existing `#authenticate` now an
|
156
|
+
alias for this when the attribute is the default 'password'.
|
63
157
|
|
64
158
|
Example:
|
65
159
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activemodel/CHANGELOG.md) for previous changes.
|
160
|
+
class User < ActiveRecord::Base
|
161
|
+
has_secure_password :recovery_password, validations: false
|
162
|
+
end
|
163
|
+
|
164
|
+
user = User.new()
|
165
|
+
user.recovery_password = "42password"
|
166
|
+
user.recovery_password_digest # => "$2a$04$iOfhwahFymCs5weB3BNH/uX..."
|
167
|
+
user.authenticate_recovery_password('42password') # => user
|
168
|
+
|
169
|
+
*Unathi Chonco*
|
170
|
+
|
171
|
+
* Add `config.active_model.i18n_customize_full_message` in order to control whether
|
172
|
+
the `full_message` error format can be overridden at the attribute or model
|
173
|
+
level in the locale files. This is `false` by default.
|
174
|
+
|
175
|
+
*Martin Larochelle*
|
176
|
+
|
177
|
+
* Rails 6 requires Ruby 2.5.0 or newer.
|
178
|
+
|
179
|
+
*Jeremy Daer*, *Kasper Timm Hansen*
|
180
|
+
|
181
|
+
|
182
|
+
Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activemodel/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -5,6 +5,8 @@ They allow for Action Pack helpers to interact with non-Active Record models,
|
|
5
5
|
for example. Active Model also helps with building custom ORMs for use outside of
|
6
6
|
the Rails framework.
|
7
7
|
|
8
|
+
You can read more about Active Model in the {Active Model Basics}[https://edgeguides.rubyonrails.org/active_model_basics.html] guide.
|
9
|
+
|
8
10
|
Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
|
9
11
|
interact with Action Pack helpers, it was required to either copy chunks of
|
10
12
|
code from Rails, or monkey patch entire helpers to make them handle objects
|
@@ -239,7 +241,7 @@ The latest version of Active Model can be installed with RubyGems:
|
|
239
241
|
|
240
242
|
Source code can be downloaded as part of the Rails project on GitHub
|
241
243
|
|
242
|
-
* https://github.com/rails/rails/tree/
|
244
|
+
* https://github.com/rails/rails/tree/master/activemodel
|
243
245
|
|
244
246
|
|
245
247
|
== License
|
@@ -253,7 +255,7 @@ Active Model is released under the MIT license:
|
|
253
255
|
|
254
256
|
API documentation is at:
|
255
257
|
|
256
|
-
*
|
258
|
+
* https://api.rubyonrails.org
|
257
259
|
|
258
260
|
Bug reports for the Ruby on Rails project can be filed here:
|
259
261
|
|
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-2019 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
|
@@ -133,10 +133,6 @@ module ActiveModel
|
|
133
133
|
end
|
134
134
|
|
135
135
|
protected
|
136
|
-
|
137
|
-
attr_reader :original_attribute
|
138
|
-
alias_method :assigned?, :original_attribute
|
139
|
-
|
140
136
|
def original_value_for_database
|
141
137
|
if assigned?
|
142
138
|
original_attribute.original_value_for_database
|
@@ -146,6 +142,9 @@ module ActiveModel
|
|
146
142
|
end
|
147
143
|
|
148
144
|
private
|
145
|
+
attr_reader :original_attribute
|
146
|
+
alias :assigned? :original_attribute
|
147
|
+
|
149
148
|
def initialize_dup(other)
|
150
149
|
if defined?(@value) && @value.duplicable?
|
151
150
|
@value = @value.dup
|
@@ -27,7 +27,7 @@ module ActiveModel
|
|
27
27
|
# cat.status # => 'sleeping'
|
28
28
|
def assign_attributes(new_attributes)
|
29
29
|
if !new_attributes.respond_to?(:stringify_keys)
|
30
|
-
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
30
|
+
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument, #{new_attributes.class} passed."
|
31
31
|
end
|
32
32
|
return if new_attributes.empty?
|
33
33
|
|
@@ -286,12 +286,12 @@ module ActiveModel
|
|
286
286
|
method_name = matcher.method_name(attr_name)
|
287
287
|
|
288
288
|
unless instance_method_already_implemented?(method_name)
|
289
|
-
generate_method = "define_method_#{matcher.
|
289
|
+
generate_method = "define_method_#{matcher.target}"
|
290
290
|
|
291
291
|
if respond_to?(generate_method, true)
|
292
292
|
send(generate_method, attr_name.to_s)
|
293
293
|
else
|
294
|
-
define_proxy_call true, generated_attribute_methods, method_name, matcher.
|
294
|
+
define_proxy_call true, generated_attribute_methods, method_name, matcher.target, attr_name.to_s
|
295
295
|
end
|
296
296
|
end
|
297
297
|
end
|
@@ -352,53 +352,54 @@ module ActiveModel
|
|
352
352
|
|
353
353
|
def attribute_method_matchers_matching(method_name)
|
354
354
|
attribute_method_matchers_cache.compute_if_absent(method_name) do
|
355
|
-
#
|
356
|
-
#
|
355
|
+
# Bump plain matcher to last place so that only methods that do not
|
356
|
+
# match any other pattern match the actual attribute name.
|
357
|
+
# This is currently only needed to support legacy usage.
|
357
358
|
matchers = attribute_method_matchers.partition(&:plain?).reverse.flatten(1)
|
358
|
-
matchers.map { |
|
359
|
+
matchers.map { |matcher| matcher.match(method_name) }.compact
|
359
360
|
end
|
360
361
|
end
|
361
362
|
|
362
363
|
# Define a method `name` in `mod` that dispatches to `send`
|
363
364
|
# using the given `extra` args. This falls back on `define_method`
|
364
365
|
# and `send` if the given names cannot be compiled.
|
365
|
-
def define_proxy_call(include_private, mod, name,
|
366
|
+
def define_proxy_call(include_private, mod, name, target, *extra)
|
366
367
|
defn = if NAME_COMPILABLE_REGEXP.match?(name)
|
367
368
|
"def #{name}(*args)"
|
368
369
|
else
|
369
370
|
"define_method(:'#{name}') do |*args|"
|
370
371
|
end
|
371
372
|
|
372
|
-
extra = (extra.map!(&:inspect) << "*args").join(", "
|
373
|
+
extra = (extra.map!(&:inspect) << "*args").join(", ")
|
373
374
|
|
374
|
-
|
375
|
-
"#{"self." unless include_private}#{
|
375
|
+
body = if CALL_COMPILABLE_REGEXP.match?(target)
|
376
|
+
"#{"self." unless include_private}#{target}(#{extra})"
|
376
377
|
else
|
377
|
-
"send(:'#{
|
378
|
+
"send(:'#{target}', #{extra})"
|
378
379
|
end
|
379
380
|
|
380
381
|
mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
381
382
|
#{defn}
|
382
|
-
#{
|
383
|
+
#{body}
|
383
384
|
end
|
384
385
|
RUBY
|
385
386
|
end
|
386
387
|
|
387
388
|
class AttributeMethodMatcher #:nodoc:
|
388
|
-
attr_reader :prefix, :suffix, :
|
389
|
+
attr_reader :prefix, :suffix, :target
|
389
390
|
|
390
|
-
AttributeMethodMatch = Struct.new(:target, :attr_name
|
391
|
+
AttributeMethodMatch = Struct.new(:target, :attr_name)
|
391
392
|
|
392
393
|
def initialize(options = {})
|
393
394
|
@prefix, @suffix = options.fetch(:prefix, ""), options.fetch(:suffix, "")
|
394
395
|
@regex = /^(?:#{Regexp.escape(@prefix)})(.*)(?:#{Regexp.escape(@suffix)})$/
|
395
|
-
@
|
396
|
+
@target = "#{@prefix}attribute#{@suffix}"
|
396
397
|
@method_name = "#{prefix}%s#{suffix}"
|
397
398
|
end
|
398
399
|
|
399
400
|
def match(method_name)
|
400
401
|
if @regex =~ method_name
|
401
|
-
AttributeMethodMatch.new(
|
402
|
+
AttributeMethodMatch.new(target, $1)
|
402
403
|
end
|
403
404
|
end
|
404
405
|
|
@@ -474,5 +475,43 @@ module ActiveModel
|
|
474
475
|
def _read_attribute(attr)
|
475
476
|
__send__(attr)
|
476
477
|
end
|
478
|
+
|
479
|
+
module AttrNames # :nodoc:
|
480
|
+
DEF_SAFE_NAME = /\A[a-zA-Z_]\w*\z/
|
481
|
+
|
482
|
+
# We want to generate the methods via module_eval rather than
|
483
|
+
# define_method, because define_method is slower on dispatch.
|
484
|
+
# Evaluating many similar methods may use more memory as the instruction
|
485
|
+
# sequences are duplicated and cached (in MRI). define_method may
|
486
|
+
# be slower on dispatch, but if you're careful about the closure
|
487
|
+
# created, then define_method will consume much less memory.
|
488
|
+
#
|
489
|
+
# But sometimes the database might return columns with
|
490
|
+
# characters that are not allowed in normal method names (like
|
491
|
+
# 'my_column(omg)'. So to work around this we first define with
|
492
|
+
# the __temp__ identifier, and then use alias method to rename
|
493
|
+
# it to what we want.
|
494
|
+
#
|
495
|
+
# We are also defining a constant to hold the frozen string of
|
496
|
+
# the attribute name. Using a constant means that we do not have
|
497
|
+
# to allocate an object on each call to the attribute method.
|
498
|
+
# Making it frozen means that it doesn't get duped when used to
|
499
|
+
# key the @attributes in read_attribute.
|
500
|
+
def self.define_attribute_accessor_method(mod, attr_name, writer: false)
|
501
|
+
method_name = "#{attr_name}#{'=' if writer}"
|
502
|
+
if attr_name.ascii_only? && DEF_SAFE_NAME.match?(attr_name)
|
503
|
+
yield method_name, "'#{attr_name}'.freeze"
|
504
|
+
else
|
505
|
+
safe_name = attr_name.unpack1("h*")
|
506
|
+
const_name = "ATTR_#{safe_name}"
|
507
|
+
const_set(const_name, attr_name) unless const_defined?(const_name)
|
508
|
+
temp_method_name = "__temp__#{safe_name}#{'=' if writer}"
|
509
|
+
attr_name_expr = "::ActiveModel::AttributeMethods::AttrNames::#{const_name}"
|
510
|
+
yield temp_method_name, attr_name_expr
|
511
|
+
mod.alias_method method_name, temp_method_name
|
512
|
+
mod.undef_method temp_method_name
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|
477
516
|
end
|
478
517
|
end
|