'Error returning promise from Ember Data

I am working on my first Ember app and got it to display the way I wanted with the route returning a static JSON object from model():

element: {
  name: "First Element",
  divisions: [{
    name: "First Division",
    sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
  }, {
    name: "Second Division",
    sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
  }]
}

Now I am trying to refactor to use Ember Data + Mirage and having an awful time.

Here’s my index.js route

export default Ember.Route.extend({
    model() {
        return this.store.find('element', 1);
    },

If I set up my Mirage config.js like this:

  this.get('/elements', function() {
    return {
      elements: [
          {
            id: 1,
            name: 'First Element',
            divisions: [1, 2]
          }
      ]
    }
  });

then I get this error:

Your Ember app tried to GET '/elements/1', but there was no route defined to handle this request.

If I set up my Mirage config.js like this:

  this.get('/elements/1', function() {
    return {
       id: 1,
       name: 'First Element',
       divisions: [1, 2]
    }
  });

then I get this error:

22:46:40.883 "Error while processing route: index" "Assertion Failed: normalizeResponse must return a valid JSON API document:
    * One or more of the following keys must be present: "data", "errors", "meta"." "EmberError@http://localhost:4200/assets/vendor.js:25582:15

EDIT:

So this isn't a solution to the problem as stated but it got me past this. I gave up on Pretender and started again creating an actual Rails server according to this excellent tutorial: http://emberigniter.com/modern-bridge-ember-and-rails-5-with-json-api/

I was able to do everything I wanted this way and if I ever want to make this a production app, I'm a lot closer.



Solution 1:[1]

So the issue is that you aren't actually adhering to the JSON API specification. You can solve this by reading Mirage's page on how to conform.

Essentially you need to either be returning an object at the top level of your JSON response in the case of a GET /foo/1 call. You'll also need to change your "elements" attribute to "data" for GET /foo and that should do the trick. Right now there isn't a simple, re-usable way to do this Mirage out of the box. The best bet right now for both issues is to use the solution presented in this issue.

Solution 2:[2]

ember error normalizeResponse must return a valid JSON API document
can be fixed in three ways

return a valid JSONAPI response

see your error message:

normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta".

  this.get('/elements/1', function() {
    return {
      data: {
        id: 1,
        name: 'First Element',
        divisions: [1, 2]
      }
    }
  });

see also https://jsonapi.org/examples/

normalize all responses

// app/serializers/application.js

import EmberData from "ember-data";

export default EmberData.JSONAPISerializer.extend({
    normalizeResponse() {
        return {
            data: this._super(...arguments),
        };
    },
    //normalize(){},
    //serialize(){},
    // ...
});

problem: error handling

by wrapping all responses in { data: ... }, they never return errors

on errors, the response should be

  this.get('/elements/1', function() {
    return {
      errors: [
        {
          id: 12345,
          title: 'title for error #12345'
        }
      ]
    }
  });

see also https://jsonapi.org/format/#error-objects

replace JSONAPI with REST

sed -i 's/JSONAPISerializer/RESTSerializer/g' app/serializers/*.js
sed -i 's/JSONAPIAdapter/RESTAdapter/g' app/adapters/*.js

ember docs: adapters and serializers

duplicate: How can ember application be integrated to use with json-server?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2