activemodel 7.1.1 → 7.1.5

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: 191a355e300ba0a18a587294a4ba721be77929a97a780f0a7dfaa519dd31ec2f
4
- data.tar.gz: f27b9ae46f6e20784e8c6eebc82994cb01cb169d3b57e622c9a772fccce1bf12
3
+ metadata.gz: 47edf9505c3471e453e228f0f5df53f81f4ef35f124245e2fa3fe21a4fe98e83
4
+ data.tar.gz: 4c693d298afbfed8f0cd722d33f2426e0f3edb7305bb581e0c4ee2a3fa1203b1
5
5
  SHA512:
6
- metadata.gz: 9985a97c165f261521b48011e8ac8a63ec61a6e6357a6ea2c9491bbed44838a492f400fccfa48f8362b7cbf53f8600a912420d57fbc473e0dcfdbfa7ed93e882
7
- data.tar.gz: 5aa0cc11f2366bd7019c10926ae34c2d0fa9e6f3acc5970dee48d25aa876efc23f71b3089e99d58e3b95375de81a17634869d962a3741037b32b7f72e1bc546e
6
+ metadata.gz: 59b03357543036b2856fdec81f20ae784e4af91a5229caa9651ca689e1d62b85a5a1cb27a1767ce7865535344f986c7c2759f3efbf31a0665e13da5b53831dcd
7
+ data.tar.gz: 1a1a03cf6c4ed8f6d3f6462a9037a6d56343accb8c1aaf39e4320f32b359fe2f14339b498b67e2a59c1be1f796bcbee79ad36641bbefac22542f10597d8b2751
data/CHANGELOG.md CHANGED
@@ -1,3 +1,72 @@
1
+ ## Rails 7.1.5 (October 30, 2024) ##
2
+
3
+ * Fix regression in `alias_attribute` to work with user defined methods.
4
+
5
+ `alias_attribute` would wrongly assume the attribute accessor was generated by Active Model.
6
+
7
+ ```ruby
8
+ class Person
9
+ include ActiveModel::AttributeMethods
10
+
11
+ define_attribute_methods :name
12
+ attr_accessor :name
13
+
14
+ alias_attribute :full_name, :name
15
+ end
16
+
17
+ person.full_name # => NoMethodError: undefined method `attribute' for an instance of Person
18
+ ```
19
+
20
+ *Jean Boussier*
21
+
22
+
23
+ ## Rails 7.1.4.2 (October 23, 2024) ##
24
+
25
+ * No changes.
26
+
27
+
28
+ ## Rails 7.1.4.1 (October 15, 2024) ##
29
+
30
+ * No changes.
31
+
32
+
33
+ ## Rails 7.1.4 (August 22, 2024) ##
34
+
35
+ * No changes.
36
+
37
+
38
+ ## Rails 7.1.3.4 (June 04, 2024) ##
39
+
40
+ * No changes.
41
+
42
+
43
+ ## Rails 7.1.3.3 (May 16, 2024) ##
44
+
45
+ * No changes.
46
+
47
+
48
+ ## Rails 7.1.3.2 (February 21, 2024) ##
49
+
50
+ * No changes.
51
+
52
+
53
+ ## Rails 7.1.3.1 (February 21, 2024) ##
54
+
55
+ * No changes.
56
+
57
+
58
+ ## Rails 7.1.3 (January 16, 2024) ##
59
+
60
+ * No changes.
61
+
62
+
63
+ ## Rails 7.1.2 (November 10, 2023) ##
64
+
65
+ * Make `==(other)` method of AttributeSet safe.
66
+
67
+ *Dmitry Pogrebnoy*
68
+
69
+
1
70
  ## Rails 7.1.1 (October 11, 2023) ##
2
71
 
3
72
  * No changes.
@@ -178,11 +178,11 @@ module ActiveModel
178
178
  def forgetting_assignment
179
179
  # If this attribute was not persisted (with a `value_for_database`
180
180
  # that might differ from `value_before_type_cast`) and `value` has not
181
- # changed in place, we can simply dup this attribute to avoid
182
- # deserialize / cast / serialize calls from computing the new
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
183
  # attribute's `value_before_type_cast`.
184
184
  if !defined?(@value_for_database) && !changed_in_place?
185
- dup
185
+ with_value_from_database(value_before_type_cast)
186
186
  else
187
187
  super
188
188
  end
@@ -215,9 +215,12 @@ module ActiveModel
215
215
  end
216
216
  end
217
217
 
218
- def generate_alias_attribute_methods(code_generator, new_name, old_name)
219
- attribute_method_patterns.each do |pattern|
220
- alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
218
+ def generate_alias_attribute_methods(code_generator, new_name, old_name) # :nodoc:
219
+ ActiveSupport::CodeGenerator.batch(code_generator, __FILE__, __LINE__) do |owner|
220
+ attribute_method_patterns.each do |pattern|
221
+ alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
222
+ end
223
+ attribute_method_patterns_cache.clear
221
224
  end
222
225
  end
223
226
 
@@ -231,7 +234,7 @@ module ActiveModel
231
234
  mangled_name = "__temp__#{target_name.unpack1("h*")}"
232
235
  end
233
236
 
234
- code_generator.define_cached_method(method_name, as: mangled_name, namespace: :alias_attribute) do |batch|
237
+ code_generator.define_cached_method(mangled_name, as: method_name, namespace: :alias_attribute) do |batch|
235
238
  body = if CALL_COMPILABLE_REGEXP.match?(target_name)
236
239
  "self.#{target_name}(#{parameters || ''})"
237
240
  else
@@ -321,25 +324,44 @@ module ActiveModel
321
324
  # person.name = 'Bob'
322
325
  # person.name # => "Bob"
323
326
  # person.name_short? # => true
324
- def define_attribute_method(attr_name, _owner: generated_attribute_methods)
327
+ def define_attribute_method(attr_name, _owner: generated_attribute_methods, as: attr_name)
325
328
  ActiveSupport::CodeGenerator.batch(_owner, __FILE__, __LINE__) do |owner|
326
329
  attribute_method_patterns.each do |pattern|
327
- method_name = pattern.method_name(attr_name)
328
-
329
- unless instance_method_already_implemented?(method_name)
330
- generate_method = "define_method_#{pattern.proxy_target}"
331
-
332
- if respond_to?(generate_method, true)
333
- send(generate_method, attr_name.to_s, owner: owner)
334
- else
335
- define_proxy_call(owner, method_name, pattern.proxy_target, pattern.parameters, attr_name.to_s, namespace: :active_model_proxy)
336
- end
337
- end
330
+ define_attribute_method_pattern(pattern, attr_name, owner: owner, as: as)
338
331
  end
339
332
  attribute_method_patterns_cache.clear
340
333
  end
341
334
  end
342
335
 
336
+ def define_attribute_method_pattern(pattern, attr_name, owner:, as:, override: false) # :nodoc:
337
+ canonical_method_name = pattern.method_name(attr_name)
338
+ public_method_name = pattern.method_name(as)
339
+
340
+ # If defining a regular attribute method, we don't override methods that are explictly
341
+ # defined in parrent classes.
342
+ if instance_method_already_implemented?(public_method_name)
343
+ # However, for `alias_attribute`, we always define the method.
344
+ # We check for override second because `instance_method_already_implemented?`
345
+ # also check for dangerous methods.
346
+ return unless override
347
+ end
348
+
349
+ generate_method = "define_method_#{pattern.proxy_target}"
350
+ if respond_to?(generate_method, true)
351
+ send(generate_method, attr_name.to_s, owner: owner, as: as)
352
+ else
353
+ define_proxy_call(
354
+ owner,
355
+ canonical_method_name,
356
+ pattern.proxy_target,
357
+ pattern.parameters,
358
+ attr_name.to_s,
359
+ namespace: :active_model_proxy,
360
+ as: public_method_name,
361
+ )
362
+ end
363
+ end
364
+
343
365
  # Removes all the previously dynamically defined methods from the class, including alias attribute methods.
344
366
  #
345
367
  # class Person
@@ -418,7 +440,7 @@ module ActiveModel
418
440
  # Define a method `name` in `mod` that dispatches to `send`
419
441
  # using the given `extra` args. This falls back on `send`
420
442
  # if the called name cannot be compiled.
421
- def define_proxy_call(code_generator, name, proxy_target, parameters, *call_args, namespace:)
443
+ def define_proxy_call(code_generator, name, proxy_target, parameters, *call_args, namespace:, as: name)
422
444
  mangled_name = name
423
445
  unless NAME_COMPILABLE_REGEXP.match?(name)
424
446
  mangled_name = "__temp__#{name.unpack1("h*")}"
@@ -426,9 +448,9 @@ module ActiveModel
426
448
 
427
449
  call_args.map!(&:inspect)
428
450
  call_args << parameters if parameters
429
- namespace = :"#{namespace}_#{proxy_target}_#{call_args.join("_")}}"
451
+ namespace = :"#{namespace}_#{proxy_target}"
430
452
 
431
- code_generator.define_cached_method(name, as: mangled_name, namespace: namespace) do |batch|
453
+ code_generator.define_cached_method(mangled_name, as: as, namespace: namespace) do |batch|
432
454
  body = if CALL_COMPILABLE_REGEXP.match?(proxy_target)
433
455
  "self.#{proxy_target}(#{call_args.join(", ")})"
434
456
  else
@@ -104,7 +104,7 @@ module ActiveModel
104
104
  end
105
105
 
106
106
  def ==(other)
107
- attributes == other.attributes
107
+ other.is_a?(AttributeSet) && attributes == other.send(:attributes)
108
108
  end
109
109
 
110
110
  protected
@@ -76,11 +76,11 @@ module ActiveModel
76
76
  end
77
77
 
78
78
  private
79
- def define_method_attribute=(name, owner:)
79
+ def define_method_attribute=(canonical_name, owner:, as: canonical_name)
80
80
  ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
81
- owner, name, writer: true,
81
+ owner, canonical_name, writer: true,
82
82
  ) do |temp_method_name, attr_name_expr|
83
- owner.define_cached_method("#{name}=", as: temp_method_name, namespace: :active_model) do |batch|
83
+ owner.define_cached_method(temp_method_name, as: "#{as}=", namespace: :active_model) do |batch|
84
84
  batch <<
85
85
  "def #{temp_method_name}(value)" <<
86
86
  " _write_attribute(#{attr_name_expr}, value)" <<
@@ -187,7 +187,7 @@ module ActiveModel
187
187
  #
188
188
  # person = Person.new(name: 'Steph')
189
189
  # person.name = 'Stephanie'
190
- # person.name_change # => ['Steph', 'Stephanie']
190
+ # person.name_was # => 'Steph'
191
191
 
192
192
  ##
193
193
  # :method: *_previous_change
@@ -63,6 +63,7 @@ module ActiveModel
63
63
 
64
64
  extend Forwardable
65
65
 
66
+ ##
66
67
  # :method: each
67
68
  #
68
69
  # :call-seq: each(&block)
@@ -74,6 +75,31 @@ module ActiveModel
74
75
  # # Will yield <#ActiveModel::Error attribute=name, type=too_short,
75
76
  # options={:count=>3}>
76
77
  # end
78
+
79
+ ##
80
+ # :method: clear
81
+ #
82
+ # :call-seq: clear
83
+ #
84
+ # Clears all errors. Clearing the errors does not, however, make the model
85
+ # valid. The next time the validations are run (for example, via
86
+ # ActiveRecord::Validations#valid?), the errors collection will be filled
87
+ # again if any validations fail.
88
+
89
+ ##
90
+ # :method: empty?
91
+ #
92
+ # :call-seq: empty?
93
+ #
94
+ # Returns true if there are no errors.
95
+
96
+ ##
97
+ # :method: size
98
+ #
99
+ # :call-seq: size
100
+ #
101
+ # Returns number of errors.
102
+
77
103
  def_delegators :@errors, :each, :clear, :empty?, :size, :uniq!
78
104
 
79
105
  # The actual array of +Error+ objects
@@ -9,7 +9,7 @@ module ActiveModel
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 1
12
+ TINY = 5
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -52,6 +52,10 @@ module ActiveModel
52
52
  # Returns a hash of the given methods with their names as keys and returned
53
53
  # values as values.
54
54
  #
55
+ # person = Person.new(id: 1, name: "bob")
56
+ # person.slice(:id, :name)
57
+ # => { "id" => 1, "name" => "bob" }
58
+ #
55
59
  #--
56
60
  # Implemented by ActiveModel::Access#slice.
57
61
 
@@ -62,6 +66,10 @@ module ActiveModel
62
66
  #
63
67
  # Returns an array of the values returned by the given methods.
64
68
  #
69
+ # person = Person.new(id: 1, name: "bob")
70
+ # person.values_at(:id, :name)
71
+ # => [1, "bob"]
72
+ #
65
73
  #--
66
74
  # Implemented by ActiveModel::Access#values_at.
67
75
  end
@@ -42,7 +42,8 @@ module ActiveModel
42
42
  end
43
43
 
44
44
  def number_to_non_number?(old_value, new_value_before_type_cast)
45
- old_value != nil && non_numeric_string?(new_value_before_type_cast.to_s)
45
+ old_value != nil && !new_value_before_type_cast.is_a?(::Numeric) &&
46
+ non_numeric_string?(new_value_before_type_cast.to_s)
46
47
  end
47
48
 
48
49
  def non_numeric_string?(value)
@@ -10,7 +10,7 @@ module ActiveModel
10
10
  # validators can be overridden inside specific classes by creating
11
11
  # custom validator classes in their place such as PresenceValidator.
12
12
  #
13
- # Examples of using the default rails validators:
13
+ # Examples of using the default \Rails validators:
14
14
  #
15
15
  # validates :username, absence: true
16
16
  # validates :terms, acceptance: true
data/lib/active_model.rb CHANGED
@@ -28,7 +28,7 @@ require "active_support/rails"
28
28
  require "active_model/version"
29
29
  require "active_model/deprecator"
30
30
 
31
- # :include: activemodel/README.rdoc
31
+ # :include: ../README.rdoc
32
32
  module ActiveModel
33
33
  extend ActiveSupport::Autoload
34
34
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.1
4
+ version: 7.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-11 00:00:00.000000000 Z
11
+ date: 2024-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.1
19
+ version: 7.1.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.1
26
+ version: 7.1.5
27
27
  description: A toolkit for building modeling frameworks like Active Record. Rich support
28
28
  for attributes, callbacks, validations, serialization, internationalization, and
29
29
  testing.
@@ -112,12 +112,12 @@ licenses:
112
112
  - MIT
113
113
  metadata:
114
114
  bug_tracker_uri: https://github.com/rails/rails/issues
115
- changelog_uri: https://github.com/rails/rails/blob/v7.1.1/activemodel/CHANGELOG.md
116
- documentation_uri: https://api.rubyonrails.org/v7.1.1/
115
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.5/activemodel/CHANGELOG.md
116
+ documentation_uri: https://api.rubyonrails.org/v7.1.5/
117
117
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
118
- source_code_uri: https://github.com/rails/rails/tree/v7.1.1/activemodel
118
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.5/activemodel
119
119
  rubygems_mfa_required: 'true'
120
- post_install_message:
120
+ post_install_message:
121
121
  rdoc_options: []
122
122
  require_paths:
123
123
  - lib
@@ -132,8 +132,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
- rubygems_version: 3.4.18
136
- signing_key:
135
+ rubygems_version: 3.5.16
136
+ signing_key:
137
137
  specification_version: 4
138
138
  summary: A toolkit for building modeling frameworks (part of Rails).
139
139
  test_files: []