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.
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