Base: read from known_attributes in respond_to_missing?#450
Merged
Conversation
seanpdoyle
added a commit
to seanpdoyle/activeresource
that referenced
this pull request
Oct 24, 2025
By including the [ActiveModel::AttributeAssignment][], the `Base` class
can access the [assign_attributes][] method for bulk assignment of
attributes **without** saving them to the server (like through
`Base#update_attributes`).
```ruby
person = Person.new
person.id # => nil
person.name # => nil
person.assign_attributes id: 1, name: "Matz"
person.id # => 1
person.name # => "Matz"
```
Support for versions prior to 7.2.0
---
This commit includes a conditional monkey-patch of the
`_assign_attribute` method when Active Model's version is < 7.2.0:
```ruby
# 7.1.5.2
def _assign_attribute(k, v)
setter = :"#{k}="
if respond_to?(setter)
public_send(setter, v)
else
raise UnknownAttributeError.new(self, k.to_s)
end
end
# 7.2.0
def _assign_attribute(k, v)
setter = :"#{k}="
public_send(setter, v)
rescue NoMethodError
if respond_to?(setter)
raise
else
raise UnknownAttributeError.new(self, k.to_s)
end
end
```
The change is necessary because the [7.1.5.2][] version queries the
instance with `respond_to?`, whereas the [7.2.0][] version skips the
query and sends the method first, falling back to a `NoMethodError`
rescue in case that it doesn't.
[rails#450][] is an alternative to including the monkey patch. If merged,
it'd make `respond_to?` behavior more like `method_missing`, so the
monkey patch would be unnecessary.
[ActiveModel::AttributeAssignment]: https://edgeapi.rubyonrails.org/classes/ActiveModel/AttributeAssignment.html
[assign_attributes]: https://edgeapi.rubyonrails.org/classes/ActiveModel/AttributeAssignment.html#method-i-assign_attributes
[7.1.5.2]: https://github.com/rails/rails/blob/v7.1.5.2/activemodel/lib/active_model/attribute_assignment.rb
[7.2.0]: https://github.com/rails/rails/blob/v7.2.0/activemodel/lib/active_model/attribute_assignment.rb
[rails#450]: rails#450
f1e2ce5 to
662f562
Compare
method_missing and respond_to_missingknown_attributes in respond_to_missing?
Prior to this commit, the `respond_to_missing?` implementation had a
conditional to supports attributes being able to be written to through
methods "did not respond to" (like `send("#{attr_name}=", value)`), as
well as `?`-suffixed predicate methods.
The `method_missing` implementation has a set of conditionals similar to
`respond_to_missing`, but with subtle variations through checking for an
attribute name's inclusion in `known_attributes` (attributes defined by
the Schema **or** assigned during `Base#load`) rather than the attribute
name's inclusion in `attributes` (the current instance's assigned
values, without any attributes declared in the Schema).
Without the implementation changes, the following tests introduced in
this commit fail:
```
1) Failure:
BaseTest#test_respond_to_known_attributes [test/cases/base_test.rb:972]:
Expected #<Person:0x000000011d0cdcf8 @attributes={}, @prefix_options={}, @persisted=false> (Person) to respond to #name=.
```
This commit changes the `respond_to_missing?` conditional to check for
the presence of the key in `known_attributes` rather than `attributes`
so that instances will respond to `=`-suffixed writers and `?`-suffixed
predicates for attributes that are declared in the resource's Schema
that have not yet been assigned to.
662f562 to
ebcc2a5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prior to this commit, the
respond_to_missing?implementation had aconditional to supports attributes being able to be written to through
methods "did not respond to" (like
send("#{attr_name}=", value)), aswell as
?-suffixed predicate methods.The
method_missingimplementation has a set of conditionals similar torespond_to_missing, but with subtle variations through checking for anattribute name's inclusion in
known_attributes(attributes defined bythe Schema or assigned during
Base#load) rather than the attributename's inclusion in
attributes(the current instance's assignedvalues, without any attributes declared in the Schema).
Without the implementation changes, the following tests introduced in
this commit fail:
This commit changes the
respond_to_missing?conditional to check forthe presence of the key in
known_attributesrather thanattributesso that instances will respond to
=-suffixed writers and?-suffixedpredicates for attributes that are declared in the resource's Schema
that have not yet been assigned to.