activemodel 8.1.3.1 → 8.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 67b65091317b383e403994b383ca5eeabbedf48f250e6fca510b5ae9f7788ba5
4
- data.tar.gz: 232cc9acf9a344bbb60964e3d44b90b983e79f29f73836b5e0a5c4bc7cc7e6c0
3
+ metadata.gz: 37ac49fcbb7194fa33c83ce420982403b8f1bcd5059e0e893a7758a2f7b1fa0f
4
+ data.tar.gz: 2f41f78730b71f3b386299fa207176cd7c477badf17917f9a540aa55397996fd
5
5
  SHA512:
6
- metadata.gz: 52e093968e2ae9b22ad7f12ed3024c614de2c7b0509ed44b90d1bcdea96d948e65904b20100272f6cc57512a5d6fbb56fab9e99b0be76574d5ceabeb96910e77
7
- data.tar.gz: 3fae2ff1ee2b877c46a45d728f3825624bec1be5d1a8d380e01b44e6cdf0eff61ae85c56f7631fc1d695e3c6c94eb0de65d615ae4af5796083907732e236e140
6
+ metadata.gz: 1cd37e1b7ed1206d74e7dc170a51a4641b9152056aa367eadb37d3315693b0ebe6b7814e391fdefaa7f3e29988c1a0aa594c3faf14990797ba1e972c5e99ffd1
7
+ data.tar.gz: 5720c98d3ddeb1aeb18caccd209d9ae3fe57a8b2995849f3876514e6e0c2ada90a401f9ac2caf8a17e4d9c49850729fd2e19c0358834d281086117c7b916baae
data/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ ## Rails 8.1.4 (September 24, 2026) ##
2
+
3
+ * Fix `ActiveModel::Errors#import` mutating the override options hash passed to it.
4
+
5
+ *Kenta Ishizaki*
6
+
7
+ * Fix `normalizes` not detecting in-place changes for attributes whose database
8
+ cast type differs from the attribute type (e.g. JSON columns), causing
9
+ normalization to be skipped on validation.
10
+
11
+ *Chedli Bourguiba*
12
+
13
+ * Fix `alias_attribute` accumulating duplicate entries in `aliases_by_attribute_name`
14
+ when called multiple times with the same arguments.
15
+
16
+ *Nicholas Jakobsen*
17
+
18
+ * Fix `normalizes` re-applying normalizations on every validation of an
19
+ unpersisted record, and speed up validation of normalized attributes.
20
+
21
+ The in-place mutation check re-ran the normalizer on every `valid?` of an
22
+ unpersisted record: wasteful for idempotent normalizers and compounded the
23
+ result for non-idempotent ones. Normalizations are now re-applied only on a
24
+ genuine in-place mutation.
25
+
26
+ *Yaroslav Markin*
27
+
28
+ * Limit the size of strings `ActiveModel::Type::Integer` will coerce with `to_i`.
29
+
30
+ Calling `to_i` on very long strings can take a long time and could be used as
31
+ a DoS vector. Integer casting now only considers the first `_limit * 4` bytes
32
+ of a string (16 bytes for a default 4-byte integer, 32 bytes for an 8-byte
33
+ bigint), which is enough to hold the maximum representable value plus a sign
34
+ or a short slug suffix.
35
+
36
+ *Aaron Patterson*, *Jean Boussier*
37
+
38
+
1
39
  ## Rails 8.1.3.1 (July 29, 2026) ##
2
40
 
3
41
  * No changes.
@@ -204,7 +204,7 @@ module ActiveModel
204
204
  old_name = old_name.to_s
205
205
  new_name = new_name.to_s
206
206
  self.attribute_aliases = attribute_aliases.merge(new_name => old_name)
207
- aliases_by_attribute_name[old_name] << new_name
207
+ aliases_by_attribute_name[old_name] |= [new_name]
208
208
  eagerly_generate_alias_attribute_methods(new_name, old_name)
209
209
  end
210
210
 
@@ -521,10 +521,18 @@ module ActiveModel
521
521
  __send__(match.proxy_target, match.attr_name, ...)
522
522
  end
523
523
 
524
+ ##
525
+ # :method: respond_to_without_attributes?
526
+ # :call-seq:
527
+ # respond_to_without_attributes?(method, include_private_methods = false)
528
+ #
529
+ # Checks whether the object responds to +method+ without searching the
530
+ # attributes.
531
+ define_method(:respond_to_without_attributes?, Kernel.instance_method(:respond_to?))
532
+
524
533
  # A +Person+ instance with a +name+ attribute can ask
525
534
  # <tt>person.respond_to?(:name)</tt>, <tt>person.respond_to?(:name=)</tt>,
526
535
  # and <tt>person.respond_to?(:name?)</tt> which will all return +true+.
527
- alias :respond_to_without_attributes? :respond_to?
528
536
  def respond_to?(method, include_private_methods = false)
529
537
  if super
530
538
  true
@@ -139,10 +139,15 @@ module ActiveModel
139
139
  private
140
140
  def normalize_changed_in_place_attributes
141
141
  self.class.normalized_attributes.each do |name|
142
- normalize_attribute(name) if attribute_changed_in_place?(name)
142
+ attribute = @attributes[name.to_s]
143
+ normalize_attribute(name) if normalized_attribute_changed_in_place?(attribute)
143
144
  end
144
145
  end
145
146
 
147
+ def normalized_attribute_changed_in_place?(attribute)
148
+ attribute.changed_in_place? && attribute.value != attribute.type_cast(attribute.value_before_type_cast)
149
+ end
150
+
146
151
  class NormalizedValueType < DelegateClass(ActiveModel::Type::Value) # :nodoc:
147
152
  include ActiveModel::Type::SerializeCastValue
148
153
 
@@ -230,7 +230,7 @@ module ActiveModel
230
230
  #
231
231
  # This method is generated for each attribute.
232
232
  #
233
- # Clears all dirty data of the attribute: current changes and previous changes.
233
+ # Clears the current changes of the attribute.
234
234
  #
235
235
  # person = Person.new(name: 'Chris')
236
236
  # person.name = 'Jason'
@@ -149,6 +149,7 @@ module ActiveModel
149
149
  # * +:attribute+ - Override the attribute the error belongs to.
150
150
  # * +:type+ - Override type of the error.
151
151
  def import(error, override_options = {})
152
+ override_options = override_options.dup
152
153
  [:attribute, :type].each do |key|
153
154
  if override_options.key?(key)
154
155
  override_options[key] = override_options[key].to_sym
@@ -311,7 +312,7 @@ module ActiveModel
311
312
  #
312
313
  # person.errors.add(:name, :too_long, count: 25)
313
314
  # person.errors.messages
314
- # # => ["is too long (maximum is 25 characters)"]
315
+ # # => {:name=>["is too long (maximum is 25 characters)"]}
315
316
  #
316
317
  # If +type+ is a proc, it will be called, allowing for things like
317
318
  # <tt>Time.now</tt> to be used within an error.
@@ -9,8 +9,8 @@ module ActiveModel
9
9
  module VERSION
10
10
  MAJOR = 8
11
11
  MINOR = 1
12
- TINY = 3
13
- PRE = "1"
12
+ TINY = 4
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -164,7 +164,9 @@ module ActiveModel
164
164
  # @data[key]
165
165
  # end
166
166
  # end
167
- alias :read_attribute_for_serialization :send
167
+ def read_attribute_for_serialization(key)
168
+ send(key)
169
+ end
168
170
 
169
171
  private
170
172
  def attribute_names_for_serialization
@@ -26,7 +26,7 @@ module ActiveModel
26
26
  # user = User.find(1)
27
27
  # user.as_json
28
28
  # # => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
29
- # # "created_at" => "2006-08-01T17:27:133.000Z", "awesome" => true}
29
+ # # "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true}
30
30
  #
31
31
  # ActiveRecord::Base.include_root_in_json = true
32
32
  #
@@ -25,11 +25,8 @@ module ActiveModel
25
25
  # event.start.sec # => 0
26
26
  # event.start.zone # => "EAT"
27
27
  #
28
- # String values are parsed using the ISO 8601 datetime format. Partial
29
- # time-only formats are also accepted.
30
- #
31
- # event.start = "06:07:08+09:00"
32
- # event.start.utc # => 1999-12-31 21:07:08 UTC
28
+ # String values are parsed using the ISO 8601 datetime format. Use the
29
+ # +:time+ type instead to parse partial time-only values.
33
30
  #
34
31
  # The degree of sub-second precision can be customized when declaring an
35
32
  # attribute:
@@ -32,7 +32,7 @@ module ActiveModel
32
32
  # bag.weight # => nil
33
33
  #
34
34
  # bag.weight = :arbitrary
35
- # bag.weight # => nil (the result of `.to_s.to_d`)
35
+ # bag.weight # => 0.0 (the result of `.to_s.to_d`)
36
36
  #
37
37
  # Decimal precision defaults to 18, and can be customized when declaring an
38
38
  # attribute:
@@ -110,7 +110,15 @@ module ActiveModel
110
110
  end
111
111
 
112
112
  def cast_value(value)
113
- value.to_i rescue nil
113
+ case value
114
+ when ::Integer
115
+ value
116
+ when ::String
117
+ str = value.bytesize > _limit * 4 ? value.byteslice(0, _limit * 4) : value
118
+ str.to_i rescue nil
119
+ else
120
+ value.to_i rescue nil
121
+ end
114
122
  end
115
123
 
116
124
  def max_value
@@ -80,7 +80,7 @@ module ActiveModel
80
80
  # <tt>on: [:create, :custom_validation_context]</tt>)
81
81
  # * <tt>:except_on</tt> - Specifies the contexts where this validation is not active.
82
82
  # Runs in all validation contexts by default +nil+. You can pass a symbol
83
- # or an array of symbols. (e.g. <tt>except: :create</tt> or
83
+ # or an array of symbols. (e.g. <tt>except_on: :create</tt> or
84
84
  # <tt>except_on: :custom_validation_context</tt> or
85
85
  # <tt>except_on: [:create, :custom_validation_context]</tt>)
86
86
  # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
@@ -72,7 +72,7 @@ module ActiveModel
72
72
  # <tt>on: [:create, :custom_validation_context]</tt>)
73
73
  # * <tt>:except_on</tt> - Specifies the contexts where this validation is not active.
74
74
  # Runs in all validation contexts by default +nil+. You can pass a symbol
75
- # or an array of symbols. (e.g. <tt>except: :create</tt> or
75
+ # or an array of symbols. (e.g. <tt>except_on: :create</tt> or
76
76
  # <tt>except_on: :custom_validation_context</tt> or
77
77
  # <tt>except_on: [:create, :custom_validation_context]</tt>)
78
78
  # * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.
@@ -144,7 +144,7 @@ module ActiveModel
144
144
  # <tt>on: [:create, :custom_validation_context]</tt>)
145
145
  # * <tt>:except_on</tt> - Specifies the contexts where this validation is not active.
146
146
  # Runs in all validation contexts by default +nil+. You can pass a symbol
147
- # or an array of symbols. (e.g. <tt>except: :create</tt> or
147
+ # or an array of symbols. (e.g. <tt>except_on: :create</tt> or
148
148
  # <tt>except_on: :custom_validation_context</tt> or
149
149
  # <tt>except_on: [:create, :custom_validation_context]</tt>)
150
150
  # * <tt>:if</tt> - Specifies a method or proc to call to determine
@@ -436,7 +436,9 @@ module ActiveModel
436
436
  # @data[key]
437
437
  # end
438
438
  # end
439
- alias :read_attribute_for_validation :send
439
+ def read_attribute_for_validation(key)
440
+ send(key)
441
+ end
440
442
 
441
443
  # Returns the context when running validations.
442
444
  def validation_context
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.3.1
4
+ version: 8.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 8.1.3.1
18
+ version: 8.1.4
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 8.1.3.1
25
+ version: 8.1.4
26
26
  description: A toolkit for building modeling frameworks like Active Record. Rich support
27
27
  for attributes, callbacks, validations, serialization, internationalization, and
28
28
  testing.
@@ -113,10 +113,10 @@ licenses:
113
113
  - MIT
114
114
  metadata:
115
115
  bug_tracker_uri: https://github.com/rails/rails/issues
116
- changelog_uri: https://github.com/rails/rails/blob/v8.1.3.1/activemodel/CHANGELOG.md
117
- documentation_uri: https://api.rubyonrails.org/v8.1.3.1/
116
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.4/activemodel/CHANGELOG.md
117
+ documentation_uri: https://api.rubyonrails.org/v8.1.4/
118
118
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
119
- source_code_uri: https://github.com/rails/rails/tree/v8.1.3.1/activemodel
119
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.4/activemodel
120
120
  rubygems_mfa_required: 'true'
121
121
  rdoc_options: []
122
122
  require_paths:
@@ -132,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
- rubygems_version: 4.0.16
135
+ rubygems_version: 4.0.20
136
136
  specification_version: 4
137
137
  summary: A toolkit for building modeling frameworks (part of Rails).
138
138
  test_files: []