0

I am trying to sideload relationship data from one API call. I have a my two models setup like so:

Contest Model (child, belongsTo):

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

export default class ContestModel extends Model {
  @attr('date') createdAt;
  @attr('string') description;

  @belongsTo('brand', { inverse: 'contests' }) brand;
}

Brand Model (parent, hasMany):

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

export default class BrandModel extends Model {
  @attr('date') createdAt;
  @attr('string') name;

  @hasMany('contest') contests;
}

I'm fetching via this line:

this.store.findRecord('contest', params.contest_id, { include: 'brand' });

This is the returned API payload:

{
  "data": {
    "type": "contest",
    "id": 1,
    "attributes": {
      "body_json": [
        {
          "question": "what time is it?",
          "answers": ["1PM", "2PM", "3PM", "4PM"]
        },
        {
          "question": "which collection is this artwork from?",
          "answers": ["botanical garden collection", "ghibli collection", "adventure collection", "swag collection"]
        }
      ],
      "created_at": "2021-05-23 18:00:00 -0700",
      "description": "a good description goes here"
    },
    "relationships": {
      "brand": {
        "links": {
          "self": "http://example.com/contests/2/relationships/brand" // not sure what this does
        },
        "data": { "type": "brand", "id": 2 }
      }
    },
    "links": {
      "self": "http://example.com/contests/2" // not sure how this is useful
    },
    "included": [
      {
        "id": 2,
        "type": "brand",
        "attributes": {
          "created_at": "2021-05-23 20:00:00 -0700",
          "name": "aloha vibe"
        }
      }
    ]
  }
}

The issue here is that calling myContest.brand returns a Proxy object just like in this SO post.

Is my API payload incorrect or is something misconfigured for my models? Or something else? I'm on Ember 3.25.3

Update from comments: When I add async: false to the Ember Data query, I get an error after this line https://github.com/emberjs/data/blob/v3.25.0/packages/store/addon/-private/system/model/internal-model.ts#L705 due to toReturn.isEmpty being true. Did I not configure my API payload? Not sure what is wrong. It seems neither createdAt nor name is populated.

enter image description here

Sticky
  • 3,671
  • 5
  • 34
  • 58
  • `myContest.brand` is expected to be a proxy. As the record is already in the store, you should be able to access its ID (`myContest.brand.id`) or any attribute of it (`myContest.brand.name`). – jelhan May 25 '21 at 09:57
  • you could declare `async: false` – Lux May 25 '21 at 15:50
  • I am unable to call `myContest.brand.id` without making a second API call – Sticky May 25 '21 at 22:31
  • I added the `async: false` and now it says: `Uncaught Error: Assertion Failed: You looked up the 'brand' relationship on a 'contest' with id 1 but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (\`belongsTo({ async: true })\`)` – Sticky May 25 '21 at 22:31
  • I updated my question with a screenshot and the offending line of code that caused the exception. Will keep digging but any ideas are definitely welcome! – Sticky May 25 '21 at 22:40

1 Answers1

2

Found the bug! The data payload needs to be in this format:

{
  "data": {
    "type": "contest",
    "id": 1,
    "attributes": {
      "body_json": [
        {
          "question": "what time is it?",
          "answers": ["1PM", "2PM", "3PM", "4PM"]
        },
        {
          "question": "which collection is this artwork from?",
          "answers": ["botanical garden collection", "ghibli collection", "adventure collection", "swag collection"]
        }
      ],
      "created_at": "2021-05-23 18:00:00 -0700",
      "description": "a good description goes here"
    },
    "relationships": {
      "brand": {
        "links": {
          "self": "http://example.com/brands/2"
        },
        "data": { "type": "brand", "id": 2 }
      }
    },
    "links": {
      "self": "http://example.com/contests/2"
    }
  },
  "included": [
    {
      "id": 2,
      "type": "brand",
      "attributes": {
        "created_at": "2021-05-23 20:00:00 -0700",
        "name": "aloha vibe"
      }
    }
  ]
}

I had nested the included within the data section but it should be at the top level with the data section. Now things are properly sideloaded and no extra API call is made :)

Sticky
  • 3,671
  • 5
  • 34
  • 58