Ember data with sync relationships

tags:  EmberJS, JavaScript

After upgrading EmberJSEmberJS
Ember Tools

Glint

Typechecker for Ember templates (Components, Helpers and Modifiers) similar to tsc in TypeScript. It specially oriented to Glimmer components in TypeScript, but it can work ...
from 3.25 to 3.28, I started to have issues with relationships with Ember Data inside Ember Tests. The hasMany relationships were empty.

I have the following configuration:

  • Ember v3.28
  • Ember Cli Mirage v2.0.0
  • Ember Data was loading most of the relationships using sync loading

What's sync loading?

In Ember Data, we understand as sync loading when we load a record with all of its relationships.

Example

We have a custom webapp with two main resources: posts and categories, and we want to access to one specific post. The ideal way in the example to load this data is having two different endpoints per resource: GET /posts/:id: and GET /categories.

In an async way of work, GET /posts/:id would look like this using a REST approach:

{
  "post": {
    [data]
    "categories": [1, 2, 3] // categories ids
  }
}

in this case we would require to call GET /categories too

In a sync way of work, we would only have one API point for achieve this:

// GET /posts/:id:
{
  "post": {
    [data]
    "categories": [
      {
        "id": 1,
        "label": "tech"
      }
    ] // categories data
  }
}

Working with sync relationships in Ember >3.28

We need to define serializer and model. Since Ember 3.28, it requires the model to specify when a hasMany relationship is async.

serializer

export default class Post extends Serializer {
  attrs = {
    categories: { embedded: 'always' },
  };

model

import Model, { attr, hasMany, belongsTo } from '@ember-data/model';

export default class Post extends Model {
  ...

  @hasMany('categories', { async: false, inverse: null }) categories

Differences between sync and async relationships

From docs:

In contrast to async relationship, accessing a sync relationship will always return the record (Model instance) for the existing local resource, or null. But it will error on access when a related resource is known to exist and it has not been loaded.

This means, a sync relationship could be empty, so it needs to be treated with care when accessing to its properties.

Note

  • Using async or sync relationships in Ember Data depends of the necessities of the webapp. There isn't an ideal path of work to solve every problem, it depends of the context of work.

References