Skip to content

Commit 02d8749

Browse files
committed
HasOne assocation will now fetch association when not included.
Thanks @JohnSmall for the original [PR #244](JsonApiClient/json_api_client#244)
1 parent 5cdb69a commit 02d8749

File tree

3 files changed

+52
-9
lines changed

3 files changed

+52
-9
lines changed

lib/jsonapi/consumer/included_data.rb

+11-8
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,20 @@ def initialize(result_set, data)
1818
end
1919

2020
def data_for(method_name, definition)
21+
# this method only returns an array. It's up to the caller to decide if it's going to return
22+
# just the first element if it's a has_one relationship.
2123
# If data is defined, pull the record from the included data
22-
return nil unless data = definition["data"]
23-
24-
if data.is_a?(Array)
25-
# has_many link
26-
data.map do |link_def|
24+
defined_data = definition["data"]
25+
return nil unless defined_data
26+
[defined_data].flatten.map do |link_def|
27+
# should return a resource record of some type for this linked document
28+
# even if there's no matching record included.
29+
if data[link_def["type"]]
2730
record_for(link_def)
31+
else
32+
# if there's no matching record in included then go and get it given the data
33+
link_def["type"].underscore.classify.constantize.find(link_def["id"]).first
2834
end
29-
else
30-
# has_one link
31-
record_for(data)
3235
end
3336
end
3437

lib/jsonapi/consumer/resource.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,12 @@ def method_missing(method, *args)
491491

492492
# look in included data
493493
if relationship_definitions.key?("data")
494-
return last_result_set.included.data_for(method, relationship_definitions)
494+
# included.data_for returns an array, if the association is a has_one, then pick the first, otherise return the whole array
495+
if association.is_a?(JSONAPI::Consumer::Associations::HasOne::Association)
496+
return last_result_set.included.data_for(method, relationship_definitions).try(:first)
497+
else
498+
return last_result_set.included.data_for(method, relationship_definitions)
499+
end
495500
end
496501

497502
if association = association_for(method)

test/unit/association_test.rb

+35
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,41 @@ def test_load_has_one_with_include
125125
assert_equal("Jeff Ching", property.owner.name)
126126
end
127127

128+
def test_load_has_one_without_include
129+
stub_request(:get, "http://example.com/properties/1")
130+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
131+
data: [
132+
{
133+
id: 1,
134+
attributes: {
135+
address: "123 Main St."
136+
},
137+
relationships: {
138+
owner: {
139+
data: {id: 1, type: "owner"}
140+
}
141+
}
142+
}
143+
]
144+
145+
}.to_json)
146+
stub_request(:get, "http://example.com/owners/1")
147+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
148+
data: [
149+
{
150+
id: 1,
151+
type: "owner",
152+
attributes: {
153+
name: "Jeff Ching"
154+
}
155+
}
156+
]
157+
}.to_json)
158+
property = Property.find(1).first
159+
assert_equal(Owner, property.owner.class)
160+
assert_equal("Jeff Ching", property.owner.name)
161+
end
162+
128163
def test_has_one_loads_nil
129164
stub_request(:get, "http://example.com/properties/1")
130165
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {

0 commit comments

Comments
 (0)