Skip to content

Commit 5d46961

Browse files
authored
Merge pull request #400 from sebasjimenez10/sj/fix-multi-word-custom-endpoint
fix: Multi-word custom endpoint not respecting route format
2 parents afeb8f8 + f7a4cef commit 5d46961

File tree

3 files changed

+104
-3
lines changed

3 files changed

+104
-3
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
## Unreleased
44

5-
## 1.22.0
65

6+
- [#400](https://github.com/JsonApiClient/json_api_client/pull/400) - Fix for multi-word custom endpoint and route format
7+
8+
## 1.22.0
79
- [#403](https://github.com/JsonApiClient/json_api_client/pull/403) - Feature: Use the association options to lookup relationship class
810
- [#406](https://github.com/JsonApiClient/json_api_client/pull/406) - Deep-merge nested `additional_params`
911

lib/json_api_client/resource.rb

+15-2
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,11 @@ def collection_endpoint(name, options = {})
260260
metaclass = class << self
261261
self
262262
end
263+
endpoint_name = _name_for_route_format(name)
263264
metaclass.instance_eval do
264265
define_method(name) do |*params|
265266
request_params = params.first || {}
266-
requestor.custom(name, options, request_params)
267+
requestor.custom(endpoint_name, options, request_params)
267268
end
268269
end
269270
end
@@ -274,10 +275,11 @@ def collection_endpoint(name, options = {})
274275
# @param options [Hash] endpoint options
275276
# @option options [Symbol] :request_method The request method (:get, :post, etc)
276277
def member_endpoint(name, options = {})
278+
endpoint_name = self._name_for_route_format(name)
277279
define_method name do |*params|
278280
request_params = params.first || {}
279281
request_params[self.class.primary_key] = attributes.fetch(self.class.primary_key)
280-
self.class.requestor.custom(name, options, request_params)
282+
self.class.requestor.custom(endpoint_name, options, request_params)
281283
end
282284
end
283285

@@ -348,6 +350,17 @@ def _build_connection(rebuild = false)
348350
yield(conn) if block_given?
349351
end
350352
end
353+
354+
def _name_for_route_format(name)
355+
case self.route_format
356+
when :dasherized_route
357+
name.to_s.dasherize
358+
when :camelized_route
359+
name.to_s.camelize(:lower)
360+
else
361+
name
362+
end
363+
end
351364
end
352365

353366
# Instantiate a new resource object

test/unit/custom_endpoint_test.rb

+86
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ class Country < TestResource
77

88
end
99

10+
class Pet < TestResource
11+
self.site = "http://example.com/"
12+
self.route_format = :dasherized_route
13+
14+
custom_endpoint :related_pets, on: :member, request_method: :get
15+
custom_endpoint :vip_pets, on: :collection, request_method: :get
16+
17+
end
18+
19+
class MythicBeasts < TestResource
20+
self.site = "http://example.com/"
21+
self.route_format = :camelized_route
22+
23+
custom_endpoint :related_beasts, on: :member, request_method: :get
24+
custom_endpoint :ancient_beasts, on: :collection, request_method: :get
25+
26+
end
27+
1028
class CustomEndpointTest < Minitest::Test
1129

1230
def test_collection_get
@@ -43,4 +61,72 @@ def test_collection_methods_should_not_add_methods_to_all_classes
4361
assert !Class.respond_to?(:autocomplete), "adding a custom method should not add methods to all classes"
4462
end
4563

64+
def test_member_dasherized_route_format_converts_custom_endpoint
65+
stub_request(:get, "http://example.com/pets/1/related-pets")
66+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
67+
data: [
68+
{id: 1, type: 'pets'},
69+
{id: 2, type: 'pets'},
70+
]
71+
}.to_json)
72+
73+
pet = Pet.new({id: 1, name: 'Otto'})
74+
pet.mark_as_persisted!
75+
76+
related_pets = pet.related_pets
77+
78+
assert_equal 2, related_pets.length
79+
assert_equal [1,2], related_pets.map(&:id)
80+
end
81+
82+
def test_collection_dasherized_route_format_converts_custom_endpoint
83+
stub_request(:get, "http://example.com/pets/vip-pets")
84+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
85+
data: [
86+
{id: 4, type: 'pets'},
87+
{id: 5, type: 'pets'},
88+
{id: 6, type: 'pets'}
89+
]
90+
}.to_json)
91+
92+
vip_pets = Pet.vip_pets
93+
94+
assert_equal 3, vip_pets.length
95+
assert_equal [4,5,6], vip_pets.map(&:id)
96+
end
97+
98+
def test_member_camelized_route_format_converts_custom_endpoint
99+
stub_request(:get, "http://example.com/mythicBeasts/1/relatedBeasts")
100+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
101+
data: [
102+
{id: 1, type: 'mythic-beasts'},
103+
{id: 2, type: 'mythic-beasts'},
104+
]
105+
}.to_json)
106+
107+
dragon = MythicBeasts.new({id: 1, name: 'Dragon'})
108+
dragon.mark_as_persisted!
109+
110+
related_beasts = dragon.related_beasts
111+
112+
assert_equal 2, related_beasts.length
113+
assert_equal [1,2], related_beasts.map(&:id)
114+
end
115+
116+
def test_collection_camelized_route_format_converts_custom_endpoint
117+
stub_request(:get, "http://example.com/mythicBeasts/ancientBeasts")
118+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
119+
data: [
120+
{id: 4, type: 'mythic-beasts'},
121+
{id: 5, type: 'mythic-beasts'},
122+
{id: 6, type: 'mythic-beasts'}
123+
]
124+
}.to_json)
125+
126+
ancient_beasts = MythicBeasts.ancient_beasts
127+
128+
assert_equal 3, ancient_beasts.length
129+
assert_equal [4,5,6], ancient_beasts.map(&:id)
130+
end
131+
46132
end

0 commit comments

Comments
 (0)