From a868196f4a0872f751dc6c7f7b833bc486a769bb Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Mon, 27 Oct 2025 23:31:38 -0400 Subject: [PATCH] `has_many`: support chaining `where` clauses Modify the `ActiveResource::Associations` module's `has_many` definition to invoke `Base.all`, rather than `Base.find(:all)` in order to utilize the deferred record fetching introduced in [#422][]. ```ruby class Person < ActiveResource::Base self.site = "https://example.com" has_many :people end person = Person.find(1) # => GET /people/1.json person.people # => GET /people.json?person_id=1 person.people.where(name: "Related") # => GET /people.json?person_id=1&name=Related ``` [#422]: https://github.com/rails/activeresource/pull/422 --- lib/active_resource/associations.rb | 2 +- test/cases/association_test.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/active_resource/associations.rb b/lib/active_resource/associations.rb index 7d27bba2f8..0009d6dca0 100644 --- a/lib/active_resource/associations.rb +++ b/lib/active_resource/associations.rb @@ -148,7 +148,7 @@ def defines_has_many_finder_method(reflection) elsif attributes.include?(method_name) attributes[method_name] elsif !new_record? - instance_variable_set(ivar_name, reflection.klass.find(:all, params: { "#{self.class.element_name}_id": self.id })) + instance_variable_set(ivar_name, reflection.klass.all(params: { "#{self.class.element_name}_id": self.id })) else instance_variable_set(ivar_name, self.class.collection_parser.new) end diff --git a/test/cases/association_test.rb b/test/cases/association_test.rb index d627b582f0..810b00eac6 100644 --- a/test/cases/association_test.rb +++ b/test/cases/association_test.rb @@ -39,6 +39,24 @@ def test_association_class_build def test_has_many External::Person.send(:has_many, :people) assert_equal 1, External::Person.reflections.select { |name, reflection| reflection.macro.eql?(:has_many) }.count + + ActiveResource::HttpMock.respond_to.get "/people.json?person_id=1", {}, { people: [ { id: 2, name: "Related" } ] }.to_json + person = External::Person.new({ id: 1 }, true) + + people = person.people + + assert_equal [ "Related" ], people.map(&:name) + end + + def test_has_many_chain + External::Person.send(:has_many, :people) + + ActiveResource::HttpMock.respond_to.get "/people.json?name=Related&person_id=1", {}, { people: [ { id: 2, name: "Related" } ] }.to_json + person = External::Person.new({ id: 1 }, true) + + people = person.people.where(name: "Related") + + assert_equal [ "Related" ], people.map(&:name) end def test_has_many_on_new_record