First question
Yes, I believe that’s a pretty standard REST paradigm. FWIW I’m mostly using RESTAdapter/Serializer and not the JSON API versions, but I think these concepts are typically pretty similar across all of the base adapters and serializers. And actually if the payload looks like what you pasted maybe you should be using the REST adapters and serializers too. Our API returns the ids with snake case, so in our API it would look like:
house: {
...
'master_bedroom_id': 2,
'kitchen_id': 5,
...
}
At that point you’d basically have three choices:
- in your model, make your relationship use, for example, the key ‘kitchen_id’/‘kitchenId’ instead of ‘kitchen’
- munge the attribute in your serializer from ‘kitchen_id’/‘kitchenId’ to ‘kitchen’
- change your backend to return just ‘kitchen’ instead of ‘kitchen_id’/‘kitchenId’
Second Question
Technically our API never returns a ‘links’ hash, but Ember Data supports it, so what we do is in the serializer we add it manually like so (this is our ‘user’ serializer, and it has a hasMany(‘account’)):
normalize: function(typeClass, hash, prop){
// add an 'accounts' link to support our 'hasMany'
hash.links = {
accounts: `/users/${hash.id}/accounts`,
};
return this._super(typeClass, hash);
},
So again, you could have your API return it, but as an alternative, you could just toss it in at the serializer level like we do (and it sounds like @Chris_Lincoln does the same).
Third Question
Yes, it would make three requests to fetch all of the records. When you define a relationship on a DS.Model, you have the option of specifying ‘async: true/false’. The default is true. This means that if a related record is not included in the main payload, it needs to look it up asynchronously using what we have been calling Options 1-3. If your API returned an id, it uses that to do a findRecord. If your API returned a links hash, it uses that. If your API returned none of those things it tries “Option 3”, constructing a URL by itself (which of course you can override to meet your needs). Ember is pretty intelligent about batching these requests and such, but yes it can add up to a lot of async requests.
One common paradigm is to include the FULL related record in a payload, often optionally. For example in our app if we’re fetching a ‘product’ model we have a query param called ‘embed_group’ which tells the API to embed the full ‘productgroup’ model instead of just the productgroup id. This prevents the front-end from making the multiple async requests because all the data is in the initial ‘product’ payload. How those payloads look exactly depends on your backend and how Ember Data digests them depends on what serializer you use, but if you’re worried about lots of async requests to your backend you could consider supporting embedding related records in your response payloads either as a rule or optionally.