jsonapi-rails
jsonapi-rails copied to clipboard
Fields of relationship objects are missing in result JSON
I have an issue with jsonapi-rails
(v0.4.0) and rendering relationships. I have a simple model consisting of Challenge
and ChallengeAnswer
; a Challenge
has_many
ChallengeAnswer
s, and a ChallengeAnswer
has a value
. Here are my serializable classes:
class SerializableChallenge < JSONAPI::Serializable::Resource
type "challenges"
has_many :answers do
data do
puts "SerializableChallenge: custom answers relation called"
@object.challenge_answers
end
end
end
class SerializableChallengeAnswer < JSONAPI::Serializable::Resource
type "challenge_answers"
belongs_to :challenge
attribute :value do
puts "SerializableChallengeAnswer: custom value attribute called"
@object.value
end
end
And this is the render call in my controller action:
render jsonapi: challenges, include: [:answers]
Now I would except that my result JSON contains a relation named answers
, and the relation contains elements with a value
. Instead, this is what I get:
"relationships": {
"answers": {
"data":[
{
"type": "challenge_answers",
"id": "cb0afe1f-fe68-4eb1-9454-8b56f419a4e9"
}
]
}
}
So the relationship's data is correctly looked up (the id
is correct), but the data fields (i.e. value
) are missing.
As you can see in my serializable classes above, I added log messages, and both messages are logged. This means that my custom value
attribute implementation is executed, but its value is not included in the result.
I tried various fixes, e.g. using fields: { answers: [:value] }
, but without success. Can someone point out what I'm doing wrong here? Maybe I'm getting the whole point of "relationship" wrong.
@drbarto Were you able to resolve this? I think that in your example changing your include
to read include: [answers: [:value]]
will add the data you are looking for to the included
array of the response, though it seems to not add the value
field to the relationships.answers.data
key.
I am trying to resolve a similar issue with multiple levels of relationships in my app that doesn't involve having to look up objects in the included
array by id/type.
@patricklewis thanks for the hint! I'm not working on that codebase anymore, so unfortunately I cannot give your suggestion a try -- but hopefully it will be helpful to others :)
IIRC I ended up writing a custom attribute which returned the nested data:
attribute :answers do
@object.challenge_answers
end
While I would have preferred the nice declarative form, this also worked and even made it simpler to generate the output format which I was after.
@drbarto Nice.. I also ended up using a similar delegation approach in my application after continuing to have trouble with multiple levels of nested relationships in the jsonapi call.
This is what I ended up with:
controller
render(
jsonapi: outcome.result,
include: [:messages],
fields: {
messages: %i[body recipient_names sender_name]
}
'message' serializer
attribute :sender_name do
@object.sender_name
end
attribute :recipient_names do
@object.recipients.includes(:person).map(&:name)
end
As you noted, this gave me more control over the format of the response and seems to be the best workaround. Thanks!