Search code examples
ember.jsember-data

Ember not setting hasMany relationship attribute after retrieving data


Foreward: There are a lot of firsts in this project, such as building my first API, first time using JSON API, first time using Ember, first time posting on SO, etc.

I'm trying to access an 'authors' hasMany attribute in my template containing the latest updates. What I access it in the template, however, nothing is returned. The models are being saved correctly, but the relationship is not being set it appears, as the length of the DS.PromiseManyArray on latest.contentAuthors is 0 while the promise is fulfilled ({ _length: 0, isFulfilled: true, isRejected: false }).

I'm using Ember 3.10 (with CLI). I have full control over my backend (LAMP running ExpressionEngine 5) and am serving API requests through a custom built plugin, though I'm not sure that matters too much as this seems to largely be a frontend problem from what I can discern.

Route

import Route from '@ember/routing/route';

export default Route.extend({
    model(){
        let latest = this.store.peekAll('latest');
        if (latest.length < 2){
            latest = this.store.query('latest', { limit: 2, include: "people" });
        }
        return latest;
    }
});

Base Model

import DS from 'ember-data';
const { Model } = DS;

export default Model.extend({
    title: DS.attr()
});

Latest Model
Edit: Removed redundant property that's not in original code

import DS from 'ember-data';
import ExpressionEngineBase from './expression-engine-base';

export default ExpressionEngineBase.extend({
    blurb: DS.attr(),
    contentAuthors: DS.hasMany('person')
});

Person Model
Edit: Removed redundant property that's not in original code

import DS from 'ember-data';
import ExpressionEngineBase from './expression-engine-base';

export default ExpressionEngineBase.extend({
    latest: DS.hasMany('latest')
});

Template

{{#each this.model as |latest|}}
    <h2>{{latest.title}}</h2>
    {{#each latest.contentAuthors as |author|}}
        <div>{{author.title}}</div>
    {{else}}
        <div>Can't find author(s)</div>
    {{/each}}
    <p>{{latest.blurb}}</p>
{{/each}}

Data sent from server
Edit: Checked this against a JSON API validator to find the original was non-conforming. I've updated my backend but this didn't solve the problem. This is now conforming according to that validator.

{
    "data": [{
        "id": "3161",
        "type": "latest",
        "attributes": {
            "title": "Amazing Video 1"
        },
        "links": {
            "self": "https:\/\/cms.example.com\/api\/v1\/video\/3161"
        },
        "relationships": {
            "people": {
                "data": [{
                    "id": "1",
                    "type": "people"
                }]
            }
        }
    }, {
        "id": "2573",
        "type": "latest",
        "attributes": {
            "title": "Amazing Article 1"
        },
        "links": {
            "self": "https:\/\/cms.example.com\/api\/v1\/white_papers_insights\/2573"
        },
        "relationships": {
            "people": {
                "data": [{
                    "id": "1",
                    "type": "people"
                }, {
                    "id": "52",
                    "type": "people"
                }]
            }
        }
    }],
    "links": {
        "self": "https:\/\/cms.example.com\/api\/v1\/latest?include=people&limit=2"
    },
    "included": [{
        "id": "1",
        "type": "people",
        "links": {
            "self": "https:\/\/cms.example.com\/api\/v1\/people\/1",
            "channel": "https:\/\/cms.example.com\/api\/v1\/people"
        },
        "attributes": {
            "title": "Great Author"
        }
    }, {
        "id": "52",
        "type": "people",
        "links": {
            "self": "https:\/\/cms.example.com\/api\/v1\/people\/52",
            "channel": "https:\/\/cms.example.com\/api\/v1\/people"
        },
        "attributes": {
            "title": "Great Co-Author"
        }
    }]
}

To reiterate, the relationship model is saving and is viewable in Ember Inspector, but the actual link/relationship is not being set.

Update: I've tried renaming types and query parameters to no avail, checking to see if inflection had anything to do with the dropped relationship.


Solution

  • The relationship in your model is named contentAuthors but in your payload you name it people.

    So instead of this:

    "people": {
      "data": [{
        "id": "1",
        "type": "people"
      }]
    }
    

    do this:

    "contentAuthors": {
      "data": [{
        "id": "1",
        "type": "people"
      }]
    }
    

    If you have contentAuthors: DS.hasMany('person') in your model.


    sidenote: latest is not a good model name. A model name should always be a noun, or at least end in one.