activemodel 5.1.7 → 5.2.8.1
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 +126 -40
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_model/attribute/user_provided_default.rb +52 -0
- data/lib/active_model/attribute.rb +248 -0
- data/lib/active_model/attribute_assignment.rb +10 -5
- data/lib/active_model/attribute_methods.rb +12 -10
- data/lib/active_model/attribute_mutation_tracker.rb +124 -0
- data/lib/active_model/attribute_set/builder.rb +126 -0
- data/lib/active_model/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_model/attribute_set.rb +114 -0
- data/lib/active_model/attributes.rb +111 -0
- data/lib/active_model/callbacks.rb +7 -2
- data/lib/active_model/conversion.rb +2 -0
- data/lib/active_model/dirty.rb +128 -57
- data/lib/active_model/errors.rb +31 -20
- data/lib/active_model/forbidden_attributes_protection.rb +2 -0
- data/lib/active_model/gem_version.rb +5 -3
- data/lib/active_model/lint.rb +14 -12
- data/lib/active_model/model.rb +2 -0
- data/lib/active_model/naming.rb +5 -3
- data/lib/active_model/railtie.rb +2 -0
- data/lib/active_model/secure_password.rb +5 -3
- data/lib/active_model/serialization.rb +3 -1
- data/lib/active_model/serializers/json.rb +3 -2
- data/lib/active_model/translation.rb +2 -0
- data/lib/active_model/type/big_integer.rb +2 -0
- data/lib/active_model/type/binary.rb +2 -0
- data/lib/active_model/type/boolean.rb +16 -1
- data/lib/active_model/type/date.rb +5 -2
- data/lib/active_model/type/date_time.rb +7 -0
- data/lib/active_model/type/decimal.rb +2 -0
- data/lib/active_model/type/float.rb +2 -0
- data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +6 -0
- data/lib/active_model/type/helpers/mutable.rb +2 -0
- data/lib/active_model/type/helpers/numeric.rb +3 -1
- data/lib/active_model/type/helpers/time_value.rb +2 -12
- data/lib/active_model/type/helpers/timezone.rb +19 -0
- data/lib/active_model/type/helpers.rb +3 -0
- data/lib/active_model/type/immutable_string.rb +2 -0
- data/lib/active_model/type/integer.rb +3 -1
- data/lib/active_model/type/registry.rb +2 -0
- data/lib/active_model/type/string.rb +2 -0
- data/lib/active_model/type/time.rb +7 -0
- data/lib/active_model/type/value.rb +6 -0
- data/lib/active_model/type.rb +7 -1
- data/lib/active_model/validations/absence.rb +2 -0
- data/lib/active_model/validations/acceptance.rb +2 -0
- data/lib/active_model/validations/callbacks.rb +12 -8
- data/lib/active_model/validations/clusivity.rb +2 -0
- data/lib/active_model/validations/confirmation.rb +3 -1
- data/lib/active_model/validations/exclusion.rb +2 -0
- data/lib/active_model/validations/format.rb +1 -0
- data/lib/active_model/validations/helper_methods.rb +2 -0
- data/lib/active_model/validations/inclusion.rb +2 -0
- data/lib/active_model/validations/length.rb +10 -2
- data/lib/active_model/validations/numericality.rb +39 -13
- data/lib/active_model/validations/presence.rb +1 -0
- data/lib/active_model/validations/validates.rb +5 -4
- data/lib/active_model/validations/with.rb +2 -0
- data/lib/active_model/validations.rb +10 -6
- data/lib/active_model/validator.rb +6 -4
- data/lib/active_model/version.rb +2 -0
- data/lib/active_model.rb +7 -2
- metadata +18 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7f6668533dd90a9b8c479fc71940522acf40284b4604e8d689d637129e6795a
|
4
|
+
data.tar.gz: 9a519747c7fc021167852457a0e03056bc68351001f61d366d32386afe584d11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f5a6ba7be9164544db261136c14337a256ad42cf9776e8364b745a6ff2c90f32f5e7a53e24ddb6032971de7e6bca59cf27808dea11d060ab5c3b20b92baef9d
|
7
|
+
data.tar.gz: b63d763a8de2b5438801b3698f33522cd68f37c22de007d752a4d1d9250b6f2ed31aab780cc07c4179670c863bb517286b85dd77ffb9cdb1624cbf5cbbe3935b
|
data/CHANGELOG.md
CHANGED
@@ -1,112 +1,198 @@
|
|
1
|
-
## Rails 5.1
|
1
|
+
## Rails 5.2.8.1 (July 12, 2022) ##
|
2
2
|
|
3
3
|
* No changes.
|
4
4
|
|
5
5
|
|
6
|
-
## Rails 5.
|
6
|
+
## Rails 5.2.8 (May 09, 2022) ##
|
7
7
|
|
8
8
|
* No changes.
|
9
9
|
|
10
10
|
|
11
|
-
## Rails 5.
|
11
|
+
## Rails 5.2.7.1 (April 26, 2022) ##
|
12
12
|
|
13
13
|
* No changes.
|
14
14
|
|
15
15
|
|
16
|
-
## Rails 5.
|
16
|
+
## Rails 5.2.7 (March 10, 2022) ##
|
17
17
|
|
18
18
|
* No changes.
|
19
19
|
|
20
20
|
|
21
|
-
## Rails 5.
|
21
|
+
## Rails 5.2.6.3 (March 08, 2022) ##
|
22
22
|
|
23
|
-
*
|
23
|
+
* No changes.
|
24
24
|
|
25
|
-
*Yoshiyuki Hirano*
|
26
25
|
|
27
|
-
## Rails 5.
|
26
|
+
## Rails 5.2.6.2 (February 11, 2022) ##
|
28
27
|
|
29
28
|
* No changes.
|
30
29
|
|
31
30
|
|
32
|
-
## Rails 5.
|
31
|
+
## Rails 5.2.6.1 (February 11, 2022) ##
|
33
32
|
|
34
33
|
* No changes.
|
35
34
|
|
36
35
|
|
37
|
-
## Rails 5.
|
36
|
+
## Rails 5.2.6 (May 05, 2021) ##
|
38
37
|
|
39
38
|
* No changes.
|
40
39
|
|
41
40
|
|
42
|
-
## Rails 5.
|
41
|
+
## Rails 5.2.5 (March 26, 2021) ##
|
43
42
|
|
44
43
|
* No changes.
|
45
44
|
|
46
45
|
|
47
|
-
## Rails 5.
|
46
|
+
## Rails 5.2.4.6 (May 05, 2021) ##
|
48
47
|
|
49
48
|
* No changes.
|
50
49
|
|
51
50
|
|
52
|
-
## Rails 5.
|
51
|
+
## Rails 5.2.4.5 (February 10, 2021) ##
|
53
52
|
|
54
53
|
* No changes.
|
55
54
|
|
56
55
|
|
57
|
-
## Rails 5.
|
56
|
+
## Rails 5.2.4.4 (September 09, 2020) ##
|
58
57
|
|
59
|
-
*
|
60
|
-
values with more scale than the schema.
|
58
|
+
* No changes.
|
61
59
|
|
62
|
-
|
60
|
+
|
61
|
+
## Rails 5.2.4.3 (May 18, 2020) ##
|
62
|
+
|
63
|
+
* No changes.
|
63
64
|
|
64
65
|
|
65
|
-
## Rails 5.
|
66
|
+
## Rails 5.2.4.2 (March 19, 2020) ##
|
66
67
|
|
67
68
|
* No changes.
|
68
69
|
|
69
70
|
|
70
|
-
## Rails 5.1
|
71
|
+
## Rails 5.2.4.1 (December 18, 2019) ##
|
72
|
+
|
73
|
+
* No changes.
|
74
|
+
|
75
|
+
|
76
|
+
## Rails 5.2.4 (November 27, 2019) ##
|
77
|
+
|
78
|
+
* Type cast falsy boolean symbols on boolean attribute as false.
|
71
79
|
|
72
|
-
|
73
|
-
frozen.
|
80
|
+
Fixes #35676.
|
74
81
|
|
75
|
-
|
82
|
+
*Ryuta Kamizono*
|
76
83
|
|
77
|
-
*Matthew Draper*
|
78
84
|
|
79
|
-
|
85
|
+
## Rails 5.2.3 (March 27, 2019) ##
|
86
|
+
|
87
|
+
* Fix date value when casting a multiparameter date hash to not convert
|
88
|
+
from Gregorian date to Julian date.
|
89
|
+
|
90
|
+
Before:
|
91
|
+
|
92
|
+
Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
|
93
|
+
=> #<Day id: nil, day: "0001-01-03", created_at: nil, updated_at: nil>
|
94
|
+
|
95
|
+
After:
|
96
|
+
|
97
|
+
Day.new({"day(1i)"=>"1", "day(2i)"=>"1", "day(3i)"=>"1"})
|
98
|
+
=> #<Day id: nil, day: "0001-01-01", created_at: nil, updated_at: nil>
|
99
|
+
|
100
|
+
Fixes #28521.
|
101
|
+
|
102
|
+
*Sayan Chakraborty*
|
103
|
+
|
104
|
+
* Fix numericality equality validation of `BigDecimal` and `Float`
|
105
|
+
by casting to `BigDecimal` on both ends of the validation.
|
106
|
+
|
107
|
+
*Gannon McGibbon*
|
108
|
+
|
109
|
+
|
110
|
+
## Rails 5.2.2.1 (March 11, 2019) ##
|
111
|
+
|
112
|
+
* No changes.
|
80
113
|
|
81
|
-
*namusyaka*
|
82
114
|
|
83
|
-
|
115
|
+
## Rails 5.2.2 (December 04, 2018) ##
|
84
116
|
|
85
|
-
|
117
|
+
* Fix numericality validator to still use value before type cast except Active Record.
|
86
118
|
|
87
|
-
|
119
|
+
Fixes #33651, #33686.
|
88
120
|
|
89
|
-
*
|
121
|
+
*Ryuta Kamizono*
|
90
122
|
|
91
|
-
* Moved DecimalWithoutScale, Text, and UnsignedInteger from Active Model to Active Record
|
92
123
|
|
93
|
-
|
124
|
+
## Rails 5.2.1.1 (November 27, 2018) ##
|
94
125
|
|
95
|
-
*
|
126
|
+
* No changes.
|
127
|
+
|
128
|
+
|
129
|
+
## Rails 5.2.1 (August 07, 2018) ##
|
130
|
+
|
131
|
+
* No changes.
|
132
|
+
|
133
|
+
|
134
|
+
## Rails 5.2.0 (April 09, 2018) ##
|
135
|
+
|
136
|
+
* Do not lose all multiple `:includes` with options in serialization.
|
137
|
+
|
138
|
+
*Mike Mangino*
|
139
|
+
|
140
|
+
* Models using the attributes API with a proc default can now be marshalled.
|
141
|
+
|
142
|
+
Fixes #31216.
|
143
|
+
|
144
|
+
*Sean Griffin*
|
145
|
+
|
146
|
+
* Fix to working before/after validation callbacks on multiple contexts.
|
147
|
+
|
148
|
+
*Yoshiyuki Hirano*
|
149
|
+
|
150
|
+
* Execute `ConfirmationValidator` validation when `_confirmation`'s value is `false`.
|
151
|
+
|
152
|
+
*bogdanvlviv*
|
153
|
+
|
154
|
+
* Allow passing a Proc or Symbol to length validator options.
|
155
|
+
|
156
|
+
*Matt Rohrer*
|
157
|
+
|
158
|
+
* Add method `#merge!` for `ActiveModel::Errors`.
|
159
|
+
|
160
|
+
*Jahfer Husain*
|
161
|
+
|
162
|
+
* Fix regression in numericality validator when comparing Decimal and Float input
|
163
|
+
values with more scale than the schema.
|
164
|
+
|
165
|
+
*Bradley Priest*
|
96
166
|
|
97
|
-
|
167
|
+
* Fix methods `#keys`, `#values` in `ActiveModel::Errors`.
|
98
168
|
|
99
|
-
|
169
|
+
Change `#keys` to only return the keys that don't have empty messages.
|
100
170
|
|
101
|
-
|
171
|
+
Change `#values` to only return the not empty values.
|
102
172
|
|
103
|
-
|
173
|
+
Example:
|
104
174
|
|
105
|
-
|
175
|
+
# Before
|
176
|
+
person = Person.new
|
177
|
+
person.errors.keys # => []
|
178
|
+
person.errors.values # => []
|
179
|
+
person.errors.messages # => {}
|
180
|
+
person.errors[:name] # => []
|
181
|
+
person.errors.messages # => {:name => []}
|
182
|
+
person.errors.keys # => [:name]
|
183
|
+
person.errors.values # => [[]]
|
106
184
|
|
107
|
-
|
185
|
+
# After
|
186
|
+
person = Person.new
|
187
|
+
person.errors.keys # => []
|
188
|
+
person.errors.values # => []
|
189
|
+
person.errors.messages # => {}
|
190
|
+
person.errors[:name] # => []
|
191
|
+
person.errors.messages # => {:name => []}
|
192
|
+
person.errors.keys # => []
|
193
|
+
person.errors.values # => []
|
108
194
|
|
109
|
-
*
|
195
|
+
*bogdanvlviv*
|
110
196
|
|
111
197
|
|
112
|
-
Please check [5-
|
198
|
+
Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activemodel/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -239,23 +239,23 @@ The latest version of Active Model can be installed with RubyGems:
|
|
239
239
|
|
240
240
|
Source code can be downloaded as part of the Rails project on GitHub
|
241
241
|
|
242
|
-
* https://github.com/rails/rails/tree/
|
242
|
+
* https://github.com/rails/rails/tree/5-2-stable/activemodel
|
243
243
|
|
244
244
|
|
245
245
|
== License
|
246
246
|
|
247
247
|
Active Model is released under the MIT license:
|
248
248
|
|
249
|
-
*
|
249
|
+
* https://opensource.org/licenses/MIT
|
250
250
|
|
251
251
|
|
252
252
|
== Support
|
253
253
|
|
254
|
-
API documentation is at
|
254
|
+
API documentation is at:
|
255
255
|
|
256
256
|
* http://api.rubyonrails.org
|
257
257
|
|
258
|
-
Bug reports
|
258
|
+
Bug reports for the Ruby on Rails project can be filed here:
|
259
259
|
|
260
260
|
* https://github.com/rails/rails/issues
|
261
261
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/attribute"
|
4
|
+
|
5
|
+
module ActiveModel
|
6
|
+
class Attribute # :nodoc:
|
7
|
+
class UserProvidedDefault < FromUser # :nodoc:
|
8
|
+
def initialize(name, value, type, database_default)
|
9
|
+
@user_provided_value = value
|
10
|
+
super(name, value, type, database_default)
|
11
|
+
end
|
12
|
+
|
13
|
+
def value_before_type_cast
|
14
|
+
if user_provided_value.is_a?(Proc)
|
15
|
+
@memoized_value_before_type_cast ||= user_provided_value.call
|
16
|
+
else
|
17
|
+
@user_provided_value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_type(type)
|
22
|
+
self.class.new(name, user_provided_value, type, original_attribute)
|
23
|
+
end
|
24
|
+
|
25
|
+
def marshal_dump
|
26
|
+
result = [
|
27
|
+
name,
|
28
|
+
value_before_type_cast,
|
29
|
+
type,
|
30
|
+
original_attribute,
|
31
|
+
]
|
32
|
+
result << value if defined?(@value)
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def marshal_load(values)
|
37
|
+
name, user_provided_value, type, original_attribute, value = values
|
38
|
+
@name = name
|
39
|
+
@user_provided_value = user_provided_value
|
40
|
+
@type = type
|
41
|
+
@original_attribute = original_attribute
|
42
|
+
if values.length == 5
|
43
|
+
@value = value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
attr_reader :user_provided_value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/duplicable"
|
4
|
+
|
5
|
+
module ActiveModel
|
6
|
+
class Attribute # :nodoc:
|
7
|
+
class << self
|
8
|
+
def from_database(name, value, type)
|
9
|
+
FromDatabase.new(name, value, type)
|
10
|
+
end
|
11
|
+
|
12
|
+
def from_user(name, value, type, original_attribute = nil)
|
13
|
+
FromUser.new(name, value, type, original_attribute)
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_cast_value(name, value, type)
|
17
|
+
WithCastValue.new(name, value, type)
|
18
|
+
end
|
19
|
+
|
20
|
+
def null(name)
|
21
|
+
Null.new(name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def uninitialized(name, type)
|
25
|
+
Uninitialized.new(name, type)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :name, :value_before_type_cast, :type
|
30
|
+
|
31
|
+
# This method should not be called directly.
|
32
|
+
# Use #from_database or #from_user
|
33
|
+
def initialize(name, value_before_type_cast, type, original_attribute = nil)
|
34
|
+
@name = name
|
35
|
+
@value_before_type_cast = value_before_type_cast
|
36
|
+
@type = type
|
37
|
+
@original_attribute = original_attribute
|
38
|
+
end
|
39
|
+
|
40
|
+
def value
|
41
|
+
# `defined?` is cheaper than `||=` when we get back falsy values
|
42
|
+
@value = type_cast(value_before_type_cast) unless defined?(@value)
|
43
|
+
@value
|
44
|
+
end
|
45
|
+
|
46
|
+
def original_value
|
47
|
+
if assigned?
|
48
|
+
original_attribute.original_value
|
49
|
+
else
|
50
|
+
type_cast(value_before_type_cast)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def value_for_database
|
55
|
+
type.serialize(value)
|
56
|
+
end
|
57
|
+
|
58
|
+
def changed?
|
59
|
+
changed_from_assignment? || changed_in_place?
|
60
|
+
end
|
61
|
+
|
62
|
+
def changed_in_place?
|
63
|
+
has_been_read? && type.changed_in_place?(original_value_for_database, value)
|
64
|
+
end
|
65
|
+
|
66
|
+
def forgetting_assignment
|
67
|
+
with_value_from_database(value_for_database)
|
68
|
+
end
|
69
|
+
|
70
|
+
def with_value_from_user(value)
|
71
|
+
type.assert_valid_value(value)
|
72
|
+
self.class.from_user(name, value, type, original_attribute || self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def with_value_from_database(value)
|
76
|
+
self.class.from_database(name, value, type)
|
77
|
+
end
|
78
|
+
|
79
|
+
def with_cast_value(value)
|
80
|
+
self.class.with_cast_value(name, value, type)
|
81
|
+
end
|
82
|
+
|
83
|
+
def with_type(type)
|
84
|
+
if changed_in_place?
|
85
|
+
with_value_from_user(value).with_type(type)
|
86
|
+
else
|
87
|
+
self.class.new(name, value_before_type_cast, type, original_attribute)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def type_cast(*)
|
92
|
+
raise NotImplementedError
|
93
|
+
end
|
94
|
+
|
95
|
+
def initialized?
|
96
|
+
true
|
97
|
+
end
|
98
|
+
|
99
|
+
def came_from_user?
|
100
|
+
false
|
101
|
+
end
|
102
|
+
|
103
|
+
def has_been_read?
|
104
|
+
defined?(@value)
|
105
|
+
end
|
106
|
+
|
107
|
+
def ==(other)
|
108
|
+
self.class == other.class &&
|
109
|
+
name == other.name &&
|
110
|
+
value_before_type_cast == other.value_before_type_cast &&
|
111
|
+
type == other.type
|
112
|
+
end
|
113
|
+
alias eql? ==
|
114
|
+
|
115
|
+
def hash
|
116
|
+
[self.class, name, value_before_type_cast, type].hash
|
117
|
+
end
|
118
|
+
|
119
|
+
def init_with(coder)
|
120
|
+
@name = coder["name"]
|
121
|
+
@value_before_type_cast = coder["value_before_type_cast"]
|
122
|
+
@type = coder["type"]
|
123
|
+
@original_attribute = coder["original_attribute"]
|
124
|
+
@value = coder["value"] if coder.map.key?("value")
|
125
|
+
end
|
126
|
+
|
127
|
+
def encode_with(coder)
|
128
|
+
coder["name"] = name
|
129
|
+
coder["value_before_type_cast"] = value_before_type_cast unless value_before_type_cast.nil?
|
130
|
+
coder["type"] = type if type
|
131
|
+
coder["original_attribute"] = original_attribute if original_attribute
|
132
|
+
coder["value"] = value if defined?(@value)
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
|
137
|
+
attr_reader :original_attribute
|
138
|
+
alias_method :assigned?, :original_attribute
|
139
|
+
|
140
|
+
def original_value_for_database
|
141
|
+
if assigned?
|
142
|
+
original_attribute.original_value_for_database
|
143
|
+
else
|
144
|
+
_original_value_for_database
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def initialize_dup(other)
|
150
|
+
if defined?(@value) && @value.duplicable?
|
151
|
+
@value = @value.dup
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def changed_from_assignment?
|
156
|
+
assigned? && type.changed?(original_value, value, value_before_type_cast)
|
157
|
+
end
|
158
|
+
|
159
|
+
def _original_value_for_database
|
160
|
+
type.serialize(original_value)
|
161
|
+
end
|
162
|
+
|
163
|
+
class FromDatabase < Attribute # :nodoc:
|
164
|
+
def type_cast(value)
|
165
|
+
type.deserialize(value)
|
166
|
+
end
|
167
|
+
|
168
|
+
def _original_value_for_database
|
169
|
+
value_before_type_cast
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class FromUser < Attribute # :nodoc:
|
174
|
+
def type_cast(value)
|
175
|
+
type.cast(value)
|
176
|
+
end
|
177
|
+
|
178
|
+
def came_from_user?
|
179
|
+
!type.value_constructed_by_mass_assignment?(value_before_type_cast)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class WithCastValue < Attribute # :nodoc:
|
184
|
+
def type_cast(value)
|
185
|
+
value
|
186
|
+
end
|
187
|
+
|
188
|
+
def changed_in_place?
|
189
|
+
false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
class Null < Attribute # :nodoc:
|
194
|
+
def initialize(name)
|
195
|
+
super(name, nil, Type.default_value)
|
196
|
+
end
|
197
|
+
|
198
|
+
def type_cast(*)
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
|
202
|
+
def with_type(type)
|
203
|
+
self.class.with_cast_value(name, nil, type)
|
204
|
+
end
|
205
|
+
|
206
|
+
def with_value_from_database(value)
|
207
|
+
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
|
208
|
+
end
|
209
|
+
alias_method :with_value_from_user, :with_value_from_database
|
210
|
+
alias_method :with_cast_value, :with_value_from_database
|
211
|
+
end
|
212
|
+
|
213
|
+
class Uninitialized < Attribute # :nodoc:
|
214
|
+
UNINITIALIZED_ORIGINAL_VALUE = Object.new
|
215
|
+
|
216
|
+
def initialize(name, type)
|
217
|
+
super(name, nil, type)
|
218
|
+
end
|
219
|
+
|
220
|
+
def value
|
221
|
+
if block_given?
|
222
|
+
yield name
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def original_value
|
227
|
+
UNINITIALIZED_ORIGINAL_VALUE
|
228
|
+
end
|
229
|
+
|
230
|
+
def value_for_database
|
231
|
+
end
|
232
|
+
|
233
|
+
def initialized?
|
234
|
+
false
|
235
|
+
end
|
236
|
+
|
237
|
+
def forgetting_assignment
|
238
|
+
dup
|
239
|
+
end
|
240
|
+
|
241
|
+
def with_type(type)
|
242
|
+
self.class.new(name, type)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
private_constant :FromDatabase, :FromUser, :Null, :Uninitialized, :WithCastValue
|
247
|
+
end
|
248
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/keys"
|
2
4
|
|
3
5
|
module ActiveModel
|
@@ -19,20 +21,22 @@ module ActiveModel
|
|
19
21
|
# cat = Cat.new
|
20
22
|
# cat.assign_attributes(name: "Gorby", status: "yawning")
|
21
23
|
# cat.name # => 'Gorby'
|
22
|
-
# cat.status => 'yawning'
|
24
|
+
# cat.status # => 'yawning'
|
23
25
|
# cat.assign_attributes(status: "sleeping")
|
24
26
|
# cat.name # => 'Gorby'
|
25
|
-
# cat.status => 'sleeping'
|
27
|
+
# cat.status # => 'sleeping'
|
26
28
|
def assign_attributes(new_attributes)
|
27
29
|
if !new_attributes.respond_to?(:stringify_keys)
|
28
30
|
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
29
31
|
end
|
30
|
-
return if new_attributes.
|
32
|
+
return if new_attributes.empty?
|
31
33
|
|
32
34
|
attributes = new_attributes.stringify_keys
|
33
35
|
_assign_attributes(sanitize_for_mass_assignment(attributes))
|
34
36
|
end
|
35
37
|
|
38
|
+
alias attributes= assign_attributes
|
39
|
+
|
36
40
|
private
|
37
41
|
|
38
42
|
def _assign_attributes(attributes)
|
@@ -42,8 +46,9 @@ module ActiveModel
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def _assign_attribute(k, v)
|
45
|
-
|
46
|
-
|
49
|
+
setter = :"#{k}="
|
50
|
+
if respond_to?(setter)
|
51
|
+
public_send(setter, v)
|
47
52
|
else
|
48
53
|
raise UnknownAttributeError.new(self, k)
|
49
54
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/map"
|
2
|
-
require "mutex_m"
|
3
4
|
|
4
5
|
module ActiveModel
|
5
6
|
# Raised when an attribute is not defined.
|
@@ -68,9 +69,8 @@ module ActiveModel
|
|
68
69
|
CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
|
69
70
|
|
70
71
|
included do
|
71
|
-
class_attribute :attribute_aliases, :
|
72
|
-
|
73
|
-
self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new]
|
72
|
+
class_attribute :attribute_aliases, instance_writer: false, default: {}
|
73
|
+
class_attribute :attribute_method_matchers, instance_writer: false, default: [ ClassMethods::AttributeMethodMatcher.new ]
|
74
74
|
end
|
75
75
|
|
76
76
|
module ClassMethods
|
@@ -328,13 +328,11 @@ module ActiveModel
|
|
328
328
|
attribute_method_matchers_cache.clear
|
329
329
|
end
|
330
330
|
|
331
|
-
def generated_attribute_methods #:nodoc:
|
332
|
-
@generated_attribute_methods ||= Module.new {
|
333
|
-
extend Mutex_m
|
334
|
-
}.tap { |mod| include mod }
|
335
|
-
end
|
336
|
-
|
337
331
|
private
|
332
|
+
def generated_attribute_methods
|
333
|
+
@generated_attribute_methods ||= Module.new.tap { |mod| include mod }
|
334
|
+
end
|
335
|
+
|
338
336
|
def instance_method_already_implemented?(method_name)
|
339
337
|
generated_attribute_methods.method_defined?(method_name)
|
340
338
|
end
|
@@ -472,5 +470,9 @@ module ActiveModel
|
|
472
470
|
def missing_attribute(attr_name, stack)
|
473
471
|
raise ActiveModel::MissingAttributeError, "missing attribute: #{attr_name}", stack
|
474
472
|
end
|
473
|
+
|
474
|
+
def _read_attribute(attr)
|
475
|
+
__send__(attr)
|
476
|
+
end
|
475
477
|
end
|
476
478
|
end
|