© The Author(s), under exclusive license to APress Media, LLC , part of Springer Nature 2021
D. TangPro Ember Datahttps://doi.org/10.1007/978-1-4842-6561-1_7

7. Nested Resource URL Paths and Relationship Links

David Tang1  
(1)
Playa Vista, CA, USA
 

Many APIs use nested resource URL paths to express relationships. An example of a nested resource URL path is /contacts/1/pets, where the collection of pet resources returned from this endpoint belongs to the contact resource with an id of 1. These endpoints are often referred to as relationship links, and Ember Data knows how to use them to load relationships. Let’s look at the default behavior of how Ember Data uses relationship links in response payloads. Then, we will look at how to tell Ember Data about relationship links if they aren’t present in an API.

The code for this chapter can be found in the chapter-7 folder of the source code for this book.

How Relationship Links Work

Ember Data supports relationship links out of the box for both the RESTAdapter and the JSONAPIAdapter. In this section, we will specifically look at relationship links with the RESTAdapter and RESTSerializer, but the same ideas apply when using JSON:API.

The RESTAdapter supports a property called links on individual resources, which contains URLs that point to related resources. For example, let’s say we have a contact model with asynchronous belongsTo and hasMany relationships :
app/models/contact.js
import Model, { attr, hasMany, belongsTo } from '@ember-data/model';
export default class ContactModel extends Model {
  @attr('string') name;
  @hasMany('pet', { async: true }) pets;
  @belongsTo('company', { async: true }) company;
}
If we made a request to /api/contacts and the response payload adhered to the RESTSerializer or the JSONSerializer formats, each contact resource in the response can have a links property :
{
  "contacts": [
    {
      "id": 1,
      "name": "David",
      "links": {
        "company": "/api/contacts/1/company",
        "pets": "/api/contacts/1/pets"
      }
    }
  ]
}
The links property can exist similarly on a single resource payload that is returned from an endpoint like /api/contacts/1:
{
  "contact": {
    "id": 1,
    "name": "David",
    "links": {
      "company": "/api/contacts/1/company",
      "pets": "/api/contacts/1/pets"
    }
  }
}

If we access contact.pets or contact.company, Ember Data will trigger a fetch using the URLs defined in links. As noted in the API documentation:

Note

The format of your links value will influence the final request URL via the urlPrefix method: Links beginning with //, http://, https://, will be used as is, with no further manipulation. Links beginning with a single / will have the current adapter’s host value prepended to it. Links with no beginning / will have a parentURL prepended to it, via the current adapter’s buildURL.

Lots of APIs offer endpoints that follow a nested resource URL path convention, but don’t return them in the links property in a resource. Let’s find out how we can tell Ember Data about these endpoints.

When APIs Don’t Return Relationship Links

In the previous chapters, we learned about the different normalization methods in serializers that allow us to intercept a payload before Ember Data uses it. To handle the missing links property, we can override one of the many normalization methods.

For example, let’s say calling store.findRecord('contact', 1) makes a request to /api/contacts/1 and returns the following payload:
{
  "contact": {
    "id": 1,
    "name": "David"
  }
}
We want to add links to this contact resource for the pet and company relationships. Although we could override a few different normalization methods, the simplest approach is to override normalize() since it operates on a single resource:
app/serializers/contact.js
import RESTSerializer from '@ember-data/serializer/rest';
export default class ContactSerializer extends RESTSerializer {
  normalize(modelClass, resourceHash) {
    resourceHash.links = {
      pets: '/api/contacts/${resourceHash.id}/pets',
      company: '/api/contacts/${resourceHash.id}/company'
    };
    return super.normalize(...arguments);
  }
}

And that’s really it! Pretty simple huh?

As mentioned earlier, JSON:API uses links too, but the response format is a little different. If you do find yourself needing to manually add links when using JSON:API, the process is similar to the example in this chapter. Visit the JSON:API specification on links1 for more details.

Summary

Now that we know how to work with relationship links, let’s move on and learn about the different ways we can work with nested data.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.171.136