diff --git a/CHANGELOG.md b/CHANGELOG.md index a01f78e..800e455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ ## Unreleased -## 1.22.0 +- [#400](https://github.com/JsonApiClient/json_api_client/pull/400) - Fix for multi-word custom endpoint and route format + +## 1.22.0 - [#403](https://github.com/JsonApiClient/json_api_client/pull/403) - Feature: Use the association options to lookup relationship class - [#406](https://github.com/JsonApiClient/json_api_client/pull/406) - Deep-merge nested `additional_params` diff --git a/lib/json_api_client/resource.rb b/lib/json_api_client/resource.rb index 0665c99..4ef7313 100644 --- a/lib/json_api_client/resource.rb +++ b/lib/json_api_client/resource.rb @@ -260,10 +260,11 @@ def collection_endpoint(name, options = {}) metaclass = class << self self end + endpoint_name = _name_for_route_format(name) metaclass.instance_eval do define_method(name) do |*params| request_params = params.first || {} - requestor.custom(name, options, request_params) + requestor.custom(endpoint_name, options, request_params) end end end @@ -274,10 +275,11 @@ def collection_endpoint(name, options = {}) # @param options [Hash] endpoint options # @option options [Symbol] :request_method The request method (:get, :post, etc) def member_endpoint(name, options = {}) + endpoint_name = self._name_for_route_format(name) define_method name do |*params| request_params = params.first || {} request_params[self.class.primary_key] = attributes.fetch(self.class.primary_key) - self.class.requestor.custom(name, options, request_params) + self.class.requestor.custom(endpoint_name, options, request_params) end end @@ -348,6 +350,17 @@ def _build_connection(rebuild = false) yield(conn) if block_given? end end + + def _name_for_route_format(name) + case self.route_format + when :dasherized_route + name.to_s.dasherize + when :camelized_route + name.to_s.camelize(:lower) + else + name + end + end end # Instantiate a new resource object diff --git a/test/unit/custom_endpoint_test.rb b/test/unit/custom_endpoint_test.rb index 017757d..e260f4d 100644 --- a/test/unit/custom_endpoint_test.rb +++ b/test/unit/custom_endpoint_test.rb @@ -7,6 +7,24 @@ class Country < TestResource end +class Pet < TestResource + self.site = "http://example.com/" + self.route_format = :dasherized_route + + custom_endpoint :related_pets, on: :member, request_method: :get + custom_endpoint :vip_pets, on: :collection, request_method: :get + +end + +class MythicBeasts < TestResource + self.site = "http://example.com/" + self.route_format = :camelized_route + + custom_endpoint :related_beasts, on: :member, request_method: :get + custom_endpoint :ancient_beasts, on: :collection, request_method: :get + +end + class CustomEndpointTest < Minitest::Test def test_collection_get @@ -43,4 +61,72 @@ def test_collection_methods_should_not_add_methods_to_all_classes assert !Class.respond_to?(:autocomplete), "adding a custom method should not add methods to all classes" end + def test_member_dasherized_route_format_converts_custom_endpoint + stub_request(:get, "http://example.com/pets/1/related-pets") + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [ + {id: 1, type: 'pets'}, + {id: 2, type: 'pets'}, + ] + }.to_json) + + pet = Pet.new({id: 1, name: 'Otto'}) + pet.mark_as_persisted! + + related_pets = pet.related_pets + + assert_equal 2, related_pets.length + assert_equal [1,2], related_pets.map(&:id) + end + + def test_collection_dasherized_route_format_converts_custom_endpoint + stub_request(:get, "http://example.com/pets/vip-pets") + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [ + {id: 4, type: 'pets'}, + {id: 5, type: 'pets'}, + {id: 6, type: 'pets'} + ] + }.to_json) + + vip_pets = Pet.vip_pets + + assert_equal 3, vip_pets.length + assert_equal [4,5,6], vip_pets.map(&:id) + end + + def test_member_camelized_route_format_converts_custom_endpoint + stub_request(:get, "http://example.com/mythicBeasts/1/relatedBeasts") + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [ + {id: 1, type: 'mythic-beasts'}, + {id: 2, type: 'mythic-beasts'}, + ] + }.to_json) + + dragon = MythicBeasts.new({id: 1, name: 'Dragon'}) + dragon.mark_as_persisted! + + related_beasts = dragon.related_beasts + + assert_equal 2, related_beasts.length + assert_equal [1,2], related_beasts.map(&:id) + end + + def test_collection_camelized_route_format_converts_custom_endpoint + stub_request(:get, "http://example.com/mythicBeasts/ancientBeasts") + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [ + {id: 4, type: 'mythic-beasts'}, + {id: 5, type: 'mythic-beasts'}, + {id: 6, type: 'mythic-beasts'} + ] + }.to_json) + + ancient_beasts = MythicBeasts.ancient_beasts + + assert_equal 3, ancient_beasts.length + assert_equal [4,5,6], ancient_beasts.map(&:id) + end + end