activemodel 5.1.7 → 5.2.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +126 -40
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_model/attribute/user_provided_default.rb +52 -0
  6. data/lib/active_model/attribute.rb +248 -0
  7. data/lib/active_model/attribute_assignment.rb +10 -5
  8. data/lib/active_model/attribute_methods.rb +12 -10
  9. data/lib/active_model/attribute_mutation_tracker.rb +124 -0
  10. data/lib/active_model/attribute_set/builder.rb +126 -0
  11. data/lib/active_model/attribute_set/yaml_encoder.rb +41 -0
  12. data/lib/active_model/attribute_set.rb +114 -0
  13. data/lib/active_model/attributes.rb +111 -0
  14. data/lib/active_model/callbacks.rb +7 -2
  15. data/lib/active_model/conversion.rb +2 -0
  16. data/lib/active_model/dirty.rb +128 -57
  17. data/lib/active_model/errors.rb +31 -20
  18. data/lib/active_model/forbidden_attributes_protection.rb +2 -0
  19. data/lib/active_model/gem_version.rb +5 -3
  20. data/lib/active_model/lint.rb +14 -12
  21. data/lib/active_model/model.rb +2 -0
  22. data/lib/active_model/naming.rb +5 -3
  23. data/lib/active_model/railtie.rb +2 -0
  24. data/lib/active_model/secure_password.rb +5 -3
  25. data/lib/active_model/serialization.rb +3 -1
  26. data/lib/active_model/serializers/json.rb +3 -2
  27. data/lib/active_model/translation.rb +2 -0
  28. data/lib/active_model/type/big_integer.rb +2 -0
  29. data/lib/active_model/type/binary.rb +2 -0
  30. data/lib/active_model/type/boolean.rb +16 -1
  31. data/lib/active_model/type/date.rb +5 -2
  32. data/lib/active_model/type/date_time.rb +7 -0
  33. data/lib/active_model/type/decimal.rb +2 -0
  34. data/lib/active_model/type/float.rb +2 -0
  35. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +6 -0
  36. data/lib/active_model/type/helpers/mutable.rb +2 -0
  37. data/lib/active_model/type/helpers/numeric.rb +3 -1
  38. data/lib/active_model/type/helpers/time_value.rb +2 -12
  39. data/lib/active_model/type/helpers/timezone.rb +19 -0
  40. data/lib/active_model/type/helpers.rb +3 -0
  41. data/lib/active_model/type/immutable_string.rb +2 -0
  42. data/lib/active_model/type/integer.rb +3 -1
  43. data/lib/active_model/type/registry.rb +2 -0
  44. data/lib/active_model/type/string.rb +2 -0
  45. data/lib/active_model/type/time.rb +7 -0
  46. data/lib/active_model/type/value.rb +6 -0
  47. data/lib/active_model/type.rb +7 -1
  48. data/lib/active_model/validations/absence.rb +2 -0
  49. data/lib/active_model/validations/acceptance.rb +2 -0
  50. data/lib/active_model/validations/callbacks.rb +12 -8
  51. data/lib/active_model/validations/clusivity.rb +2 -0
  52. data/lib/active_model/validations/confirmation.rb +3 -1
  53. data/lib/active_model/validations/exclusion.rb +2 -0
  54. data/lib/active_model/validations/format.rb +1 -0
  55. data/lib/active_model/validations/helper_methods.rb +2 -0
  56. data/lib/active_model/validations/inclusion.rb +2 -0
  57. data/lib/active_model/validations/length.rb +10 -2
  58. data/lib/active_model/validations/numericality.rb +39 -13
  59. data/lib/active_model/validations/presence.rb +1 -0
  60. data/lib/active_model/validations/validates.rb +5 -4
  61. data/lib/active_model/validations/with.rb +2 -0
  62. data/lib/active_model/validations.rb +10 -6
  63. data/lib/active_model/validator.rb +6 -4
  64. data/lib/active_model/version.rb +2 -0
  65. data/lib/active_model.rb +7 -2
  66. metadata +18 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 176c2e4b4046605da54dbff663e8cca4e615bf2f985f11ce19befb86dd54b6e5
4
- data.tar.gz: f94d4e883f254dc43a58abe127653920a852ceb437d2e96163418b3c9f64b273
3
+ metadata.gz: d7f6668533dd90a9b8c479fc71940522acf40284b4604e8d689d637129e6795a
4
+ data.tar.gz: 9a519747c7fc021167852457a0e03056bc68351001f61d366d32386afe584d11
5
5
  SHA512:
6
- metadata.gz: 2571ca4fd35c99bbf91349f87a261a5e4821f8d2ec9172303c1d85536111ce843305bea423b3794e22a800270b9db8e9f97a23d981ab95ebda973547e8b0ad74
7
- data.tar.gz: ce929044a81485baad038cfa449ee198720ed326afcb0aa3a782da558c7c4569e7f9ee433043fb5f48ddbbdfb26df75d376f2e1e256da13e80a4350126b06722
6
+ metadata.gz: 0f5a6ba7be9164544db261136c14337a256ad42cf9776e8364b745a6ff2c90f32f5e7a53e24ddb6032971de7e6bca59cf27808dea11d060ab5c3b20b92baef9d
7
+ data.tar.gz: b63d763a8de2b5438801b3698f33522cd68f37c22de007d752a4d1d9250b6f2ed31aab780cc07c4179670c863bb517286b85dd77ffb9cdb1624cbf5cbbe3935b
data/CHANGELOG.md CHANGED
@@ -1,112 +1,198 @@
1
- ## Rails 5.1.7 (March 27, 2019) ##
1
+ ## Rails 5.2.8.1 (July 12, 2022) ##
2
2
 
3
3
  * No changes.
4
4
 
5
5
 
6
- ## Rails 5.1.6.2 (March 11, 2019) ##
6
+ ## Rails 5.2.8 (May 09, 2022) ##
7
7
 
8
8
  * No changes.
9
9
 
10
10
 
11
- ## Rails 5.1.6.1 (November 27, 2018) ##
11
+ ## Rails 5.2.7.1 (April 26, 2022) ##
12
12
 
13
13
  * No changes.
14
14
 
15
15
 
16
- ## Rails 5.1.6 (March 29, 2018) ##
16
+ ## Rails 5.2.7 (March 10, 2022) ##
17
17
 
18
18
  * No changes.
19
19
 
20
20
 
21
- ## Rails 5.1.5 (February 14, 2018) ##
21
+ ## Rails 5.2.6.3 (March 08, 2022) ##
22
22
 
23
- * Fix to working before/after validation callbacks on multiple contexts.
23
+ * No changes.
24
24
 
25
- *Yoshiyuki Hirano*
26
25
 
27
- ## Rails 5.1.4 (September 07, 2017) ##
26
+ ## Rails 5.2.6.2 (February 11, 2022) ##
28
27
 
29
28
  * No changes.
30
29
 
31
30
 
32
- ## Rails 5.1.4.rc1 (August 24, 2017) ##
31
+ ## Rails 5.2.6.1 (February 11, 2022) ##
33
32
 
34
33
  * No changes.
35
34
 
36
35
 
37
- ## Rails 5.1.3 (August 03, 2017) ##
36
+ ## Rails 5.2.6 (May 05, 2021) ##
38
37
 
39
38
  * No changes.
40
39
 
41
40
 
42
- ## Rails 5.1.3.rc3 (July 31, 2017) ##
41
+ ## Rails 5.2.5 (March 26, 2021) ##
43
42
 
44
43
  * No changes.
45
44
 
46
45
 
47
- ## Rails 5.1.3.rc2 (July 25, 2017) ##
46
+ ## Rails 5.2.4.6 (May 05, 2021) ##
48
47
 
49
48
  * No changes.
50
49
 
51
50
 
52
- ## Rails 5.1.3.rc1 (July 19, 2017) ##
51
+ ## Rails 5.2.4.5 (February 10, 2021) ##
53
52
 
54
53
  * No changes.
55
54
 
56
55
 
57
- ## Rails 5.1.2 (June 26, 2017) ##
56
+ ## Rails 5.2.4.4 (September 09, 2020) ##
58
57
 
59
- * Fix regression in numericality validator when comparing Decimal and Float input
60
- values with more scale than the schema.
58
+ * No changes.
61
59
 
62
- *Bradley Priest*
60
+
61
+ ## Rails 5.2.4.3 (May 18, 2020) ##
62
+
63
+ * No changes.
63
64
 
64
65
 
65
- ## Rails 5.1.1 (May 12, 2017) ##
66
+ ## Rails 5.2.4.2 (March 19, 2020) ##
66
67
 
67
68
  * No changes.
68
69
 
69
70
 
70
- ## Rails 5.1.0 (April 27, 2017) ##
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
- * The original string assigned to a model attribute is no longer incorrectly
73
- frozen.
80
+ Fixes #35676.
74
81
 
75
- Fixes #24185, #28718.
82
+ *Ryuta Kamizono*
76
83
 
77
- *Matthew Draper*
78
84
 
79
- * Avoid converting integer as a string into float.
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
- * Remove deprecated behavior that halts callbacks when the return is false.
115
+ ## Rails 5.2.2 (December 04, 2018) ##
84
116
 
85
- *Rafael Mendonça França*
117
+ * Fix numericality validator to still use value before type cast except Active Record.
86
118
 
87
- * Remove unused `ActiveModel::TestCase` class.
119
+ Fixes #33651, #33686.
88
120
 
89
- *Yuji Yaginuma*
121
+ *Ryuta Kamizono*
90
122
 
91
- * Moved DecimalWithoutScale, Text, and UnsignedInteger from Active Model to Active Record
92
123
 
93
- *Iain Beeston*
124
+ ## Rails 5.2.1.1 (November 27, 2018) ##
94
125
 
95
- * Allow indifferent access in `ActiveModel::Errors`.
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
- `#include?`, `#has_key?`, `#key?`, `#delete` and `#full_messages_for`.
167
+ * Fix methods `#keys`, `#values` in `ActiveModel::Errors`.
98
168
 
99
- *Kenichi Kamiya*
169
+ Change `#keys` to only return the keys that don't have empty messages.
100
170
 
101
- * Removed deprecated `:tokenizer` in the length validator.
171
+ Change `#values` to only return the not empty values.
102
172
 
103
- *Rafael Mendonça França*
173
+ Example:
104
174
 
105
- * Removed deprecated methods in `ActiveModel::Errors`.
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
- `#get`, `#set`, `[]=`, `add_on_empty` and `add_on_blank`.
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
- *Rafael Mendonça França*
195
+ *bogdanvlviv*
110
196
 
111
197
 
112
- Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/activemodel/CHANGELOG.md) for previous changes.
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2017 David Heinemeier Hansson
1
+ Copyright (c) 2004-2018 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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/master/activemodel
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
- * http://www.opensource.org/licenses/MIT
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 can be filed for the Ruby on Rails project here:
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.nil? || new_attributes.empty?
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
- if respond_to?("#{k}=")
46
- public_send("#{k}=", v)
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, :attribute_method_matchers, instance_writer: false
72
- self.attribute_aliases = {}
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