From 22443115d57ccedd6c8c6fd8e7aaf998e4cc8c5b Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Sat, 18 Jan 2025 20:19:24 -0500 Subject: [PATCH] Mix `ActiveModel::AttributeAssignment` into `Base` 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.schema = { name: "string" } person = Person.new person.id # => nil person.name # => nil person.assign_attributes id: 1, name: "Matz" person.id # => 1 person.name # => "Matz" ``` [ActiveModel::AttributeAssignment]: https://edgeapi.rubyonrails.org/classes/ActiveModel/AttributeAssignment.html [assign_attributes]: https://edgeapi.rubyonrails.org/classes/ActiveModel/AttributeAssignment.html#method-i-assign_attributes --- lib/active_resource/base.rb | 2 +- test/cases/base_test.rb | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/active_resource/base.rb b/lib/active_resource/base.rb index 8662a5925a..91fa8a1f47 100644 --- a/lib/active_resource/base.rb +++ b/lib/active_resource/base.rb @@ -1857,7 +1857,7 @@ class Base extend ActiveResource::Associations include Callbacks, CustomMethods, Validations, Serialization - include ActiveModel::Conversion + include ActiveModel::AttributeAssignment, ActiveModel::Conversion include ActiveModel::ForbiddenAttributesProtection include ActiveModel::Serializers::JSON include ActiveModel::Serializers::Xml diff --git a/test/cases/base_test.rb b/test/cases/base_test.rb index 462920ac92..dd0cda2d4a 100644 --- a/test/cases/base_test.rb +++ b/test/cases/base_test.rb @@ -1008,6 +1008,28 @@ def test_predicate_for_an_unknown_attribute_returns_nil assert_not_predicate post, :unknown_attribute? end + def test_assign_attributes_to_known_attributes + previous_schema = Person.schema + Person.schema = { name: "string" } + + matz = Person.new + + matz.assign_attributes "id" => 1, :name => "Matz" + + assert_equal 1, matz.id + assert_equal "Matz", matz.name + ensure + Person.schema = previous_schema + end + + def test_assign_attributes_assigns_to_loaded_attributes + matz = Person.new(name: "matz") + + assert_changes -> { matz.name }, from: "matz", to: "Matz" do + matz.assign_attributes(name: "Matz") + end + end + def test_custom_header Person.headers["key"] = "value" assert_raise(ActiveResource::ResourceNotFound) { Person.find(4) }