From 0bbeaa9db1433f1e95b57da3196ccf2a5b56cd61 Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Fri, 11 Jul 2025 15:40:28 -0400 Subject: [PATCH] Add `ActiveResource::Base.collection_url` Introduce the `.collection_url` method to leverage the [collection_path][] method and to complement the pre-existing [element_url][] and [element_path][] pairing. [collection_path]: https://rubydoc.info/gems/activeresource/ActiveResource/Base#collection_path-class_method [element_path]: https://rubydoc.info/gems/activeresource/ActiveResource/Base#element_path-class_method [element_url]: https://rubydoc.info/gems/activeresource/ActiveResource/Base#element_url-class_method --- lib/active_resource/base.rb | 25 +++++++++++++++++++++++++ test/cases/base_test.rb | 20 ++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/active_resource/base.rb b/lib/active_resource/base.rb index 29376f081d..24520cd199 100644 --- a/lib/active_resource/base.rb +++ b/lib/active_resource/base.rb @@ -886,6 +886,31 @@ def collection_path(prefix_options = {}, query_options = nil) "#{prefix(prefix_options)}#{collection_name}#{format_extension}#{query_string(query_options)}" end + # Gets the collection URL for the REST resources. If the +query_options+ parameter is omitted, Rails + # will split from the +prefix_options+. + # + # ==== Options + # * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., :account_id => 19 + # would yield a URL like /accounts/19/purchases.json). + # * +query_options+ - A hash to add items to the query string for the request. + # + # ==== Examples + # Post.collection_url + # # => https://example.com/posts.json + # + # Comment.collection_url(:post_id => 5) + # # => https://example.com/posts/5/comments.json + # + # Comment.collection_url(:post_id => 5, :active => 1) + # # => https://example.com/posts/5/comments.json?active=1 + # + # Comment.collection_url({:post_id => 5}, {:active => 1}) + # # => https://example.com/posts/5/comments.json?active=1 + # + def collection_url(prefix_options = {}, query_options = nil) + URI.join(site, collection_path(prefix_options, query_options)).to_s + end + alias_method :set_primary_key, :primary_key= # :nodoc: # Builds a new, unsaved record using the default values from the remote server so diff --git a/test/cases/base_test.rb b/test/cases/base_test.rb index 3689b4234d..c39cea7595 100644 --- a/test/cases/base_test.rb +++ b/test/cases/base_test.rb @@ -773,6 +773,10 @@ def test_collection_path assert_equal "/people.json", Person.collection_path end + def test_collection_url + assert_equal "http://37s.sunrise.i:3000/people.json", Person.collection_url + end + def test_collection_path_with_parameters assert_equal "/people.json?gender=male", Person.collection_path(gender: "male") assert_equal "/people.json?gender=false", Person.collection_path(gender: false) @@ -789,6 +793,22 @@ def test_collection_path_with_parameters assert_equal "/people.json?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred", Person.collection_path(struct: { :a => [2, 1], "b" => "fred" }) end + def test_collection_url_with_parameters + assert_equal "http://37s.sunrise.i:3000/people.json?name=Test", Person.collection_url(name: "Test") + assert_equal "http://37s.sunrise.i:3000/people.json?name=false", Person.collection_url(name: false) + assert_equal "http://37s.sunrise.i:3000/people.json?name=", Person.collection_url(name: nil) + + assert_equal "http://37s.sunrise.i:3000/people.json?name=Test", Person.collection_url("name" => "Test") + + # Use includes? because ordering of param hash is not guaranteed + assert Person.collection_url(name: "Test", student: true).include?("/people.json?") + assert Person.collection_url(name: "Test", student: true).include?("name=Test") + assert Person.collection_url(name: "Test", student: true).include?("student=true") + + assert_equal "http://37s.sunrise.i:3000/people.json?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false", Person.collection_url(name: ["bob", "your uncle+me", nil, false]) + assert_equal "http://37s.sunrise.i:3000/people.json?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred", Person.collection_url(struct: { :a => [2, 1], "b" => "fred" }) + end + def test_custom_element_path assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, person_id: 1) assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, "person_id" => 1)