activemodel 7.0.8.7 → 7.2.3
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 +38 -249
- data/MIT-LICENSE +1 -1
- data/README.rdoc +19 -19
- data/lib/active_model/access.rb +16 -0
- data/lib/active_model/api.rb +5 -5
- data/lib/active_model/attribute/user_provided_default.rb +4 -0
- data/lib/active_model/attribute.rb +27 -2
- data/lib/active_model/attribute_assignment.rb +5 -3
- data/lib/active_model/attribute_methods.rb +145 -85
- data/lib/active_model/attribute_registration.rb +117 -0
- data/lib/active_model/attribute_set.rb +10 -1
- data/lib/active_model/attributes.rb +78 -48
- data/lib/active_model/callbacks.rb +6 -6
- data/lib/active_model/conversion.rb +14 -4
- data/lib/active_model/deprecator.rb +7 -0
- data/lib/active_model/dirty.rb +134 -13
- data/lib/active_model/error.rb +4 -3
- data/lib/active_model/errors.rb +37 -6
- data/lib/active_model/forbidden_attributes_protection.rb +2 -0
- data/lib/active_model/gem_version.rb +4 -4
- data/lib/active_model/lint.rb +1 -1
- data/lib/active_model/locale/en.yml +1 -0
- data/lib/active_model/model.rb +34 -2
- data/lib/active_model/naming.rb +29 -10
- data/lib/active_model/railtie.rb +4 -0
- data/lib/active_model/secure_password.rb +63 -25
- data/lib/active_model/serialization.rb +3 -3
- data/lib/active_model/serializers/json.rb +1 -1
- data/lib/active_model/translation.rb +30 -16
- data/lib/active_model/type/big_integer.rb +23 -1
- data/lib/active_model/type/binary.rb +7 -1
- data/lib/active_model/type/boolean.rb +11 -9
- data/lib/active_model/type/date.rb +28 -2
- data/lib/active_model/type/date_time.rb +45 -3
- data/lib/active_model/type/decimal.rb +39 -1
- data/lib/active_model/type/float.rb +30 -1
- data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +5 -1
- data/lib/active_model/type/helpers/numeric.rb +6 -1
- data/lib/active_model/type/helpers/time_value.rb +50 -13
- data/lib/active_model/type/helpers/timezone.rb +5 -1
- data/lib/active_model/type/immutable_string.rb +37 -1
- data/lib/active_model/type/integer.rb +44 -1
- data/lib/active_model/type/registry.rb +2 -3
- data/lib/active_model/type/serialize_cast_value.rb +47 -0
- data/lib/active_model/type/string.rb +9 -1
- data/lib/active_model/type/time.rb +48 -7
- data/lib/active_model/type/value.rb +17 -1
- data/lib/active_model/type.rb +1 -0
- data/lib/active_model/validations/absence.rb +1 -1
- data/lib/active_model/validations/acceptance.rb +1 -1
- data/lib/active_model/validations/callbacks.rb +5 -5
- data/lib/active_model/validations/clusivity.rb +5 -8
- data/lib/active_model/validations/comparability.rb +0 -11
- data/lib/active_model/validations/comparison.rb +16 -8
- data/lib/active_model/validations/format.rb +6 -7
- data/lib/active_model/validations/length.rb +10 -8
- data/lib/active_model/validations/numericality.rb +35 -23
- data/lib/active_model/validations/presence.rb +1 -1
- data/lib/active_model/validations/resolve_value.rb +26 -0
- data/lib/active_model/validations/validates.rb +4 -4
- data/lib/active_model/validations/with.rb +9 -2
- data/lib/active_model/validations.rb +48 -11
- data/lib/active_model/validator.rb +7 -5
- data/lib/active_model/version.rb +1 -1
- data/lib/active_model.rb +5 -1
- metadata +14 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cd11eb90ab99961854be28823adafd875c43c0ee7d7e6067b2af752a1f183f88
|
|
4
|
+
data.tar.gz: 690c5e435225163f5ebee8eadeb5ebdcb6b9269140be69471e187d4bce24b7fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c0c5710770bf4a62c45d71ccc25629f73c39f45c9c38f013abd7947c63e72c4e35ec0bfe85da0b32a4ab3c62892aadea62b78ca64e04666015a318339d544c00
|
|
7
|
+
data.tar.gz: e1db829ae10154c73749425d12c1749df1cbbb9f6485c68badac84f2bd945d91ae9c0022eb0d5e886c11edced5e13476be20bf49605e2b318cb2d1dd3e58d9a8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,299 +1,88 @@
|
|
|
1
|
-
## Rails 7.
|
|
1
|
+
## Rails 7.2.3 (October 28, 2025) ##
|
|
2
2
|
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Rails 7.0.8.6 (October 23, 2024) ##
|
|
7
|
-
|
|
8
|
-
* No changes.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Rails 7.0.8.5 (October 15, 2024) ##
|
|
12
|
-
|
|
13
|
-
* No changes.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
## Rails 7.0.8.4 (June 04, 2024) ##
|
|
17
|
-
|
|
18
|
-
* No changes.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## Rails 7.0.8.3 (May 17, 2024) ##
|
|
22
|
-
|
|
23
|
-
* No changes.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
## Rails 7.0.8.2 (May 16, 2024) ##
|
|
27
|
-
|
|
28
|
-
* No changes.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## Rails 7.0.8.1 (February 21, 2024) ##
|
|
32
|
-
|
|
33
|
-
* No changes.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Rails 7.0.8 (September 09, 2023) ##
|
|
37
|
-
|
|
38
|
-
* No changes.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## Rails 7.0.7.2 (August 22, 2023) ##
|
|
42
|
-
|
|
43
|
-
* No changes.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## Rails 7.0.7.1 (August 22, 2023) ##
|
|
47
|
-
|
|
48
|
-
* No changes.
|
|
3
|
+
* Fix `has_secure_password` to perform confirmation validation of the password even when blank.
|
|
49
4
|
|
|
5
|
+
The validation was incorrectly skipped when the password only contained whitespace characters.
|
|
50
6
|
|
|
51
|
-
|
|
7
|
+
*Fabio Sangiovanni*
|
|
52
8
|
|
|
53
|
-
*
|
|
9
|
+
* Handle missing attributes for `ActiveModel::Translation#human_attribute_name`.
|
|
54
10
|
|
|
55
11
|
*zzak*
|
|
56
12
|
|
|
57
|
-
*
|
|
58
|
-
`ActiveRecord::Base` and allow for overriding aspects of the `ActiveModel::Model` class.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
## Rails 7.0.6 (June 29, 2023) ##
|
|
62
|
-
|
|
63
|
-
* No changes.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
## Rails 7.0.5.1 (June 26, 2023) ##
|
|
67
|
-
|
|
68
|
-
* No changes.
|
|
69
|
-
|
|
13
|
+
* Fix `ActiveModel::AttributeAssignment#assign_attributes` to accept objects without `each`.
|
|
70
14
|
|
|
71
|
-
|
|
15
|
+
*Kouhei Yanagita*
|
|
72
16
|
|
|
73
|
-
* No changes.
|
|
74
17
|
|
|
75
|
-
|
|
76
|
-
## Rails 7.0.4.3 (March 13, 2023) ##
|
|
18
|
+
## Rails 7.2.2.2 (August 13, 2025) ##
|
|
77
19
|
|
|
78
20
|
* No changes.
|
|
79
21
|
|
|
80
22
|
|
|
81
|
-
## Rails 7.
|
|
23
|
+
## Rails 7.2.2.1 (December 10, 2024) ##
|
|
82
24
|
|
|
83
25
|
* No changes.
|
|
84
26
|
|
|
85
27
|
|
|
86
|
-
## Rails 7.
|
|
28
|
+
## Rails 7.2.2 (October 30, 2024) ##
|
|
87
29
|
|
|
88
|
-
*
|
|
30
|
+
* Fix regression in `alias_attribute` to work with user defined methods.
|
|
89
31
|
|
|
32
|
+
`alias_attribute` would wrongly assume the attribute accessor was generated by Active Model.
|
|
90
33
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
34
|
+
```ruby
|
|
35
|
+
class Person
|
|
36
|
+
include ActiveModel::AttributeMethods
|
|
94
37
|
|
|
95
|
-
|
|
96
|
-
|
|
38
|
+
define_attribute_methods :name
|
|
39
|
+
attr_accessor :name
|
|
97
40
|
|
|
98
|
-
|
|
99
|
-
class A
|
|
100
|
-
attribute_method_suffix "_changed?"
|
|
101
|
-
define_attribute_methods :x
|
|
41
|
+
alias_attribute :full_name, :name
|
|
102
42
|
end
|
|
103
43
|
|
|
104
|
-
|
|
105
|
-
attribute_method_suffix "?"
|
|
106
|
-
define_attribute_methods :x_changed
|
|
107
|
-
end
|
|
44
|
+
person.full_name # => NoMethodError: undefined method `attribute' for an instance of Person
|
|
108
45
|
```
|
|
109
46
|
|
|
110
47
|
*Jean Boussier*
|
|
111
48
|
|
|
112
|
-
## Rails 7.0.3.1 (July 12, 2022) ##
|
|
113
49
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
## Rails 7.0.3 (May 09, 2022) ##
|
|
50
|
+
## Rails 7.2.1.2 (October 23, 2024) ##
|
|
118
51
|
|
|
119
52
|
* No changes.
|
|
120
53
|
|
|
121
54
|
|
|
122
|
-
## Rails 7.
|
|
55
|
+
## Rails 7.2.1.1 (October 15, 2024) ##
|
|
123
56
|
|
|
124
57
|
* No changes.
|
|
125
58
|
|
|
126
59
|
|
|
127
|
-
## Rails 7.
|
|
60
|
+
## Rails 7.2.1 (August 22, 2024) ##
|
|
128
61
|
|
|
129
62
|
* No changes.
|
|
130
63
|
|
|
131
64
|
|
|
132
|
-
## Rails 7.
|
|
133
|
-
|
|
134
|
-
* No changes.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
## Rails 7.0.2.1 (February 11, 2022) ##
|
|
138
|
-
|
|
139
|
-
* No changes.
|
|
65
|
+
## Rails 7.2.0 (August 09, 2024) ##
|
|
140
66
|
|
|
67
|
+
* Fix a bug where type casting of string to `Time` and `DateTime` doesn't
|
|
68
|
+
calculate minus minute value in TZ offset correctly.
|
|
141
69
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
* Use different cache namespace for proxy calls
|
|
145
|
-
|
|
146
|
-
Models can currently have different attribute bodies for the same method
|
|
147
|
-
names, leading to conflicts. Adding a new namespace `:active_model_proxy`
|
|
148
|
-
fixes the issue.
|
|
149
|
-
|
|
150
|
-
*Chris Salzberg*
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
## Rails 7.0.1 (January 06, 2022) ##
|
|
154
|
-
|
|
155
|
-
* No changes.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
## Rails 7.0.0 (December 15, 2021) ##
|
|
159
|
-
|
|
160
|
-
* No changes.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
## Rails 7.0.0.rc3 (December 14, 2021) ##
|
|
164
|
-
|
|
165
|
-
* No changes.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
## Rails 7.0.0.rc2 (December 14, 2021) ##
|
|
169
|
-
|
|
170
|
-
* No changes.
|
|
171
|
-
|
|
172
|
-
## Rails 7.0.0.rc1 (December 06, 2021) ##
|
|
173
|
-
|
|
174
|
-
* Remove support to Marshal load Rails 5.x `ActiveModel::AttributeSet` format.
|
|
175
|
-
|
|
176
|
-
*Rafael Mendonça França*
|
|
177
|
-
|
|
178
|
-
* Remove support to Marshal and YAML load Rails 5.x error format.
|
|
179
|
-
|
|
180
|
-
*Rafael Mendonça França*
|
|
181
|
-
|
|
182
|
-
* Remove deprecated support to use `[]=` in `ActiveModel::Errors#messages`.
|
|
183
|
-
|
|
184
|
-
*Rafael Mendonça França*
|
|
185
|
-
|
|
186
|
-
* Remove deprecated support to `delete` errors from `ActiveModel::Errors#messages`.
|
|
187
|
-
|
|
188
|
-
*Rafael Mendonça França*
|
|
189
|
-
|
|
190
|
-
* Remove deprecated support to `clear` errors from `ActiveModel::Errors#messages`.
|
|
191
|
-
|
|
192
|
-
*Rafael Mendonça França*
|
|
193
|
-
|
|
194
|
-
* Remove deprecated support concat errors to `ActiveModel::Errors#messages`.
|
|
195
|
-
|
|
196
|
-
*Rafael Mendonça França*
|
|
197
|
-
|
|
198
|
-
* Remove deprecated `ActiveModel::Errors#to_xml`.
|
|
199
|
-
|
|
200
|
-
*Rafael Mendonça França*
|
|
201
|
-
|
|
202
|
-
* Remove deprecated `ActiveModel::Errors#keys`.
|
|
203
|
-
|
|
204
|
-
*Rafael Mendonça França*
|
|
205
|
-
|
|
206
|
-
* Remove deprecated `ActiveModel::Errors#values`.
|
|
207
|
-
|
|
208
|
-
*Rafael Mendonça França*
|
|
209
|
-
|
|
210
|
-
* Remove deprecated `ActiveModel::Errors#slice!`.
|
|
211
|
-
|
|
212
|
-
*Rafael Mendonça França*
|
|
213
|
-
|
|
214
|
-
* Remove deprecated `ActiveModel::Errors#to_h`.
|
|
215
|
-
|
|
216
|
-
*Rafael Mendonça França*
|
|
217
|
-
|
|
218
|
-
* Remove deprecated enumeration of `ActiveModel::Errors` instances as a Hash.
|
|
219
|
-
|
|
220
|
-
*Rafael Mendonça França*
|
|
221
|
-
|
|
222
|
-
* Clear secure password cache if password is set to `nil`
|
|
223
|
-
|
|
224
|
-
Before:
|
|
225
|
-
|
|
226
|
-
user.password = 'something'
|
|
227
|
-
user.password = nil
|
|
228
|
-
|
|
229
|
-
user.password # => 'something'
|
|
230
|
-
|
|
231
|
-
Now:
|
|
232
|
-
|
|
233
|
-
user.password = 'something'
|
|
234
|
-
user.password = nil
|
|
235
|
-
|
|
236
|
-
user.password # => nil
|
|
237
|
-
|
|
238
|
-
*Markus Doits*
|
|
239
|
-
|
|
240
|
-
## Rails 7.0.0.alpha2 (September 15, 2021) ##
|
|
241
|
-
|
|
242
|
-
* No changes.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
## Rails 7.0.0.alpha1 (September 15, 2021) ##
|
|
246
|
-
|
|
247
|
-
* Introduce `ActiveModel::API`.
|
|
248
|
-
|
|
249
|
-
Make `ActiveModel::API` the minimum API to talk with Action Pack and Action View.
|
|
250
|
-
This will allow adding more functionality to `ActiveModel::Model`.
|
|
251
|
-
|
|
252
|
-
*Petrik de Heus*, *Nathaniel Watts*
|
|
253
|
-
|
|
254
|
-
* Fix dirty check for Float::NaN and BigDecimal::NaN.
|
|
255
|
-
|
|
256
|
-
Float::NaN and BigDecimal::NaN in Ruby are [special values](https://bugs.ruby-lang.org/issues/1720)
|
|
257
|
-
and can't be compared with `==`.
|
|
258
|
-
|
|
259
|
-
*Marcelo Lauxen*
|
|
260
|
-
|
|
261
|
-
* Fix `to_json` for `ActiveModel::Dirty` object.
|
|
262
|
-
|
|
263
|
-
Exclude `mutations_from_database` attribute from json as it lead to recursion.
|
|
264
|
-
|
|
265
|
-
*Anil Maurya*
|
|
266
|
-
|
|
267
|
-
* Add `ActiveModel::AttributeSet#values_for_database`.
|
|
268
|
-
|
|
269
|
-
Returns attributes with values for assignment to the database.
|
|
270
|
-
|
|
271
|
-
*Chris Salzberg*
|
|
272
|
-
|
|
273
|
-
* Fix delegation in ActiveModel::Type::Registry#lookup and ActiveModel::Type.lookup.
|
|
274
|
-
|
|
275
|
-
Passing a last positional argument `{}` would be incorrectly considered as keyword argument.
|
|
276
|
-
|
|
277
|
-
*Benoit Daloze*
|
|
278
|
-
|
|
279
|
-
* Cache and re-use generated attribute methods.
|
|
280
|
-
|
|
281
|
-
Generated methods with identical implementations will now share their instruction sequences
|
|
282
|
-
leading to reduced memory retention, and slightly faster load time.
|
|
283
|
-
|
|
284
|
-
*Jean Boussier*
|
|
285
|
-
|
|
286
|
-
* Add `in: range` parameter to `numericality` validator.
|
|
70
|
+
*Akira Matsuda*
|
|
287
71
|
|
|
288
|
-
|
|
72
|
+
* Port the `type_for_attribute` method to Active Model. Classes that include
|
|
73
|
+
`ActiveModel::Attributes` will now provide this method. This method behaves
|
|
74
|
+
the same for Active Model as it does for Active Record.
|
|
289
75
|
|
|
290
|
-
|
|
291
|
-
|
|
76
|
+
```ruby
|
|
77
|
+
class MyModel
|
|
78
|
+
include ActiveModel::Attributes
|
|
292
79
|
|
|
293
|
-
|
|
80
|
+
attribute :my_attribute, :integer
|
|
81
|
+
end
|
|
294
82
|
|
|
295
|
-
|
|
83
|
+
MyModel.type_for_attribute(:my_attribute) # => #<ActiveModel::Type::Integer ...>
|
|
84
|
+
```
|
|
296
85
|
|
|
297
|
-
*
|
|
86
|
+
*Jonathan Hefner*
|
|
298
87
|
|
|
299
|
-
Please check [
|
|
88
|
+
Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activemodel/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
= Active Model -- model interfaces for Rails
|
|
1
|
+
= Active Model -- model interfaces for \Rails
|
|
2
2
|
|
|
3
3
|
Active Model provides a known set of interfaces for usage in model classes.
|
|
4
4
|
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
|
-
the Rails framework.
|
|
6
|
+
the \Rails framework.
|
|
7
7
|
|
|
8
|
-
You can read more about Active Model in the {Active Model Basics}[https://
|
|
8
|
+
You can read more about Active Model in the {Active Model Basics}[https://guides.rubyonrails.org/active_model_basics.html] guide.
|
|
9
9
|
|
|
10
|
-
Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
|
|
10
|
+
Prior to \Rails 3.0, if a plugin or gem developer wanted to have an object
|
|
11
11
|
interact with Action Pack helpers, it was required to either copy chunks of
|
|
12
|
-
code from Rails, or monkey patch entire helpers to make them handle objects
|
|
12
|
+
code from \Rails, or monkey patch entire helpers to make them handle objects
|
|
13
13
|
that did not exactly conform to the Active Record interface. This would result
|
|
14
14
|
in code duplication and fragile applications that broke on upgrades. Active
|
|
15
15
|
Model solves this by defining an explicit API. You can read more about the
|
|
16
|
-
API in
|
|
16
|
+
API in +ActiveModel::Lint::Tests+.
|
|
17
17
|
|
|
18
18
|
Active Model provides a default module that implements the basic API required
|
|
19
|
-
to integrate with Action Pack out of the box:
|
|
19
|
+
to integrate with Action Pack out of the box: ActiveModel::API.
|
|
20
20
|
|
|
21
21
|
class Person
|
|
22
22
|
include ActiveModel::API
|
|
@@ -32,7 +32,7 @@ to integrate with Action Pack out of the box: <tt>ActiveModel::API</tt>.
|
|
|
32
32
|
|
|
33
33
|
It includes model name introspections, conversions, translations and
|
|
34
34
|
validations, resulting in a class suitable to be used with Action Pack.
|
|
35
|
-
See
|
|
35
|
+
See ActiveModel::API for more examples.
|
|
36
36
|
|
|
37
37
|
Active Model also provides the following functionality to have ORM-like
|
|
38
38
|
behavior out of the box:
|
|
@@ -56,7 +56,7 @@ behavior out of the box:
|
|
|
56
56
|
person.clear_name
|
|
57
57
|
person.clear_age
|
|
58
58
|
|
|
59
|
-
{Learn more}[
|
|
59
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/AttributeMethods.html]
|
|
60
60
|
|
|
61
61
|
* Callbacks for certain operations
|
|
62
62
|
|
|
@@ -74,7 +74,7 @@ behavior out of the box:
|
|
|
74
74
|
This generates +before_create+, +around_create+ and +after_create+
|
|
75
75
|
class methods that wrap your create method.
|
|
76
76
|
|
|
77
|
-
{Learn more}[
|
|
77
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Callbacks.html]
|
|
78
78
|
|
|
79
79
|
* Tracking value changes
|
|
80
80
|
|
|
@@ -110,7 +110,7 @@ behavior out of the box:
|
|
|
110
110
|
person.save
|
|
111
111
|
person.previous_changes # => {'name' => ['bob, 'robert']}
|
|
112
112
|
|
|
113
|
-
{Learn more}[
|
|
113
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Dirty.html]
|
|
114
114
|
|
|
115
115
|
* Adding +errors+ interface to objects
|
|
116
116
|
|
|
@@ -141,7 +141,7 @@ behavior out of the box:
|
|
|
141
141
|
person.errors.full_messages
|
|
142
142
|
# => ["Name cannot be nil"]
|
|
143
143
|
|
|
144
|
-
{Learn more}[
|
|
144
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Errors.html]
|
|
145
145
|
|
|
146
146
|
* Model name introspection
|
|
147
147
|
|
|
@@ -152,11 +152,11 @@ behavior out of the box:
|
|
|
152
152
|
NamedPerson.model_name.name # => "NamedPerson"
|
|
153
153
|
NamedPerson.model_name.human # => "Named person"
|
|
154
154
|
|
|
155
|
-
{Learn more}[
|
|
155
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Naming.html]
|
|
156
156
|
|
|
157
157
|
* Making objects serializable
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
ActiveModel::Serialization provides a standard interface for your object
|
|
160
160
|
to provide +to_json+ serialization.
|
|
161
161
|
|
|
162
162
|
class SerialPerson
|
|
@@ -179,7 +179,7 @@ behavior out of the box:
|
|
|
179
179
|
s = SerialPerson.new
|
|
180
180
|
s.to_json # => "{\"name\":null}"
|
|
181
181
|
|
|
182
|
-
{Learn more}[
|
|
182
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Serialization.html]
|
|
183
183
|
|
|
184
184
|
* Internationalization (i18n) support
|
|
185
185
|
|
|
@@ -190,7 +190,7 @@ behavior out of the box:
|
|
|
190
190
|
Person.human_attribute_name('my_attribute')
|
|
191
191
|
# => "My attribute"
|
|
192
192
|
|
|
193
|
-
{Learn more}[
|
|
193
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Translation.html]
|
|
194
194
|
|
|
195
195
|
* Validation support
|
|
196
196
|
|
|
@@ -208,7 +208,7 @@ behavior out of the box:
|
|
|
208
208
|
person.first_name = 'zoolander'
|
|
209
209
|
person.valid? # => false
|
|
210
210
|
|
|
211
|
-
{Learn more}[
|
|
211
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Validations.html]
|
|
212
212
|
|
|
213
213
|
* Custom validators
|
|
214
214
|
|
|
@@ -230,7 +230,7 @@ behavior out of the box:
|
|
|
230
230
|
p.name = "Bob"
|
|
231
231
|
p.valid? # => true
|
|
232
232
|
|
|
233
|
-
{Learn more}[
|
|
233
|
+
{Learn more}[https://api.rubyonrails.org/classes/ActiveModel/Validator.html]
|
|
234
234
|
|
|
235
235
|
|
|
236
236
|
== Download and installation
|
|
@@ -261,6 +261,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
|
|
|
261
261
|
|
|
262
262
|
* https://github.com/rails/rails/issues
|
|
263
263
|
|
|
264
|
-
Feature requests should be discussed on the
|
|
264
|
+
Feature requests should be discussed on the rubyonrails-core forum here:
|
|
265
265
|
|
|
266
266
|
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
|
4
|
+
require "active_support/core_ext/hash/indifferent_access"
|
|
5
|
+
|
|
6
|
+
module ActiveModel
|
|
7
|
+
module Access # :nodoc:
|
|
8
|
+
def slice(*methods)
|
|
9
|
+
methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def values_at(*methods)
|
|
13
|
+
methods.flatten.map! { |method| public_send(method) }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/active_model/api.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveModel
|
|
4
|
-
#
|
|
4
|
+
# = Active \Model \API
|
|
5
5
|
#
|
|
6
6
|
# Includes the required interface for an object to interact with
|
|
7
|
-
# Action Pack and Action View, using different Active Model modules.
|
|
7
|
+
# Action Pack and Action View, using different Active \Model modules.
|
|
8
8
|
# It includes model name introspections, conversions, translations, and
|
|
9
9
|
# validations. Besides that, it allows you to initialize the object with a
|
|
10
10
|
# hash of attributes, pretty much like Active Record does.
|
|
@@ -20,7 +20,7 @@ module ActiveModel
|
|
|
20
20
|
# person.name # => "bob"
|
|
21
21
|
# person.age # => "18"
|
|
22
22
|
#
|
|
23
|
-
# Note that, by default,
|
|
23
|
+
# Note that, by default, +ActiveModel::API+ implements #persisted?
|
|
24
24
|
# to return +false+, which is the most common case. You may want to override
|
|
25
25
|
# it in your class to simulate a different scenario:
|
|
26
26
|
#
|
|
@@ -36,7 +36,7 @@ module ActiveModel
|
|
|
36
36
|
# person = Person.new(id: 1, name: 'bob')
|
|
37
37
|
# person.persisted? # => true
|
|
38
38
|
#
|
|
39
|
-
# Also, if for some reason you need to run code on
|
|
39
|
+
# Also, if for some reason you need to run code on initialize ( ::new ), make
|
|
40
40
|
# sure you call +super+ if you want the attributes hash initialization to
|
|
41
41
|
# happen.
|
|
42
42
|
#
|
|
@@ -54,7 +54,7 @@ module ActiveModel
|
|
|
54
54
|
# person.omg # => true
|
|
55
55
|
#
|
|
56
56
|
# For more detailed information on other functionalities available, please
|
|
57
|
-
# refer to the specific modules included in
|
|
57
|
+
# refer to the specific modules included in +ActiveModel::API+
|
|
58
58
|
# (see below).
|
|
59
59
|
module API
|
|
60
60
|
extend ActiveSupport::Concern
|
|
@@ -4,6 +4,10 @@ require "active_model/attribute"
|
|
|
4
4
|
|
|
5
5
|
module ActiveModel
|
|
6
6
|
class Attribute # :nodoc:
|
|
7
|
+
def with_user_default(value)
|
|
8
|
+
UserProvidedDefault.new(name, value, type, self.is_a?(FromDatabase) ? self : original_attribute)
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
class UserProvidedDefault < FromUser # :nodoc:
|
|
8
12
|
def initialize(name, value, type, database_default)
|
|
9
13
|
@user_provided_value = value
|
|
@@ -53,7 +53,10 @@ module ActiveModel
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def value_for_database
|
|
56
|
-
type.
|
|
56
|
+
if !defined?(@value_for_database) || type.changed_in_place?(@value_for_database, value)
|
|
57
|
+
@value_for_database = _value_for_database
|
|
58
|
+
end
|
|
59
|
+
@value_for_database
|
|
57
60
|
end
|
|
58
61
|
|
|
59
62
|
def serializable?(&block)
|
|
@@ -150,7 +153,7 @@ module ActiveModel
|
|
|
150
153
|
alias :assigned? :original_attribute
|
|
151
154
|
|
|
152
155
|
def initialize_dup(other)
|
|
153
|
-
if
|
|
156
|
+
if @value&.duplicable?
|
|
154
157
|
@value = @value.dup
|
|
155
158
|
end
|
|
156
159
|
end
|
|
@@ -159,6 +162,10 @@ module ActiveModel
|
|
|
159
162
|
assigned? && type.changed?(original_value, value, value_before_type_cast)
|
|
160
163
|
end
|
|
161
164
|
|
|
165
|
+
def _value_for_database
|
|
166
|
+
type.serialize(value)
|
|
167
|
+
end
|
|
168
|
+
|
|
162
169
|
def _original_value_for_database
|
|
163
170
|
type.serialize(original_value)
|
|
164
171
|
end
|
|
@@ -168,6 +175,19 @@ module ActiveModel
|
|
|
168
175
|
type.deserialize(value)
|
|
169
176
|
end
|
|
170
177
|
|
|
178
|
+
def forgetting_assignment
|
|
179
|
+
# If this attribute was not persisted (with a `value_for_database`
|
|
180
|
+
# that might differ from `value_before_type_cast`) and `value` has not
|
|
181
|
+
# changed in place, we can use the existing `value_before_type_cast`
|
|
182
|
+
# to avoid deserialize / cast / serialize calls from computing the new
|
|
183
|
+
# attribute's `value_before_type_cast`.
|
|
184
|
+
if !defined?(@value_for_database) && !changed_in_place?
|
|
185
|
+
with_value_from_database(value_before_type_cast)
|
|
186
|
+
else
|
|
187
|
+
super
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
171
191
|
private
|
|
172
192
|
def _original_value_for_database
|
|
173
193
|
value_before_type_cast
|
|
@@ -182,6 +202,11 @@ module ActiveModel
|
|
|
182
202
|
def came_from_user?
|
|
183
203
|
!type.value_constructed_by_mass_assignment?(value_before_type_cast)
|
|
184
204
|
end
|
|
205
|
+
|
|
206
|
+
private
|
|
207
|
+
def _value_for_database
|
|
208
|
+
Type::SerializeCastValue.serialize(type, value)
|
|
209
|
+
end
|
|
185
210
|
end
|
|
186
211
|
|
|
187
212
|
class WithCastValue < Attribute # :nodoc:
|
|
@@ -10,7 +10,7 @@ module ActiveModel
|
|
|
10
10
|
# keys matching the attribute names.
|
|
11
11
|
#
|
|
12
12
|
# If the passed hash responds to <tt>permitted?</tt> method and the return value
|
|
13
|
-
# of this method is +false+ an
|
|
13
|
+
# of this method is +false+ an ActiveModel::ForbiddenAttributesError
|
|
14
14
|
# exception is raised.
|
|
15
15
|
#
|
|
16
16
|
# class Cat
|
|
@@ -38,15 +38,17 @@ module ActiveModel
|
|
|
38
38
|
|
|
39
39
|
private
|
|
40
40
|
def _assign_attributes(attributes)
|
|
41
|
-
attributes.
|
|
41
|
+
attributes.each_pair do |k, v|
|
|
42
42
|
_assign_attribute(k, v)
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def _assign_attribute(k, v)
|
|
47
47
|
setter = :"#{k}="
|
|
48
|
+
public_send(setter, v)
|
|
49
|
+
rescue NoMethodError
|
|
48
50
|
if respond_to?(setter)
|
|
49
|
-
|
|
51
|
+
raise
|
|
50
52
|
else
|
|
51
53
|
raise UnknownAttributeError.new(self, k.to_s)
|
|
52
54
|
end
|