Ember async relationships stopped fulfilling in 2.12.0


#1

I’m sure this can be filed under “I’m missing something obvious”, but I’ve been trying to wrestle with an Ember upgrade for ~2 days now with no luck. I’m going from 2.11.1 -> 2.12.0

I have a model foo, which hasMany of bar. This used to work perfectly fine in 2.11.1. The parent and child fields are all printed as expected.

<ul>
  {{#each model.foo as |foo|}}
    <li>Id: {{foo.id}} Arr({{foo.bar.length}})</li>
    <ul>
      {{#each foo.bar as |bar|}}
        <li>{{bar.id}}: {{bar.static}}, {{bar.field1}}</li>
      {{/each}}
    </ul>
  {{/each}}
</ul>

The exact same code is not working for me in 2.12.0 after an upgrade. Note that the ids, and length of the chid/hasMany array are there, but the value of field1 is not.

The bar model looks like this.

export default DS.Model.extend({
  static: 'something static',
  field1: DS.attr('string')
});

I tried re-creating in a Twiddle and things are working perfectly fine there. It’s probably some happy accident/something I’m doing wrong that allowed it to ever work in 2.11.1, but I cannot figure it out, and it’s made the upgrade process extremely frustrating.

I tried switching from yarn back to npm for upgrading thinking maybe a version of some dependency was screwed up, I tried locking in specific package.json versions, and running ember init and starting over about a dozen different times. I tried stripping the template and model and adapter and serializer down to the bare bones. Everything is fine in 2.11.1, but fails with no error in 2.12.0

I tried outputting the data in the route, and I see the child/hasMany data there in 2.11.1, but not in 2.12.0. This is sloppy/ugly, but it works in 2.11.1. I can see the value of field1. In 2.12.0 the value is undefined.

  model() {
    return Ember.RSVP.hash({
      foo: this.get('store').query('foo', {
        accountId: 2
      }).then((foos) => {
        foos.forEach((foo) => {
          console.log(foo.get('bar.length'));
          foo.get('bar').then((bars) => {
            bars.forEach((bar) => {
              console.log(bar.get('id'), bar.get('static'), bar.get('field1'));
            })
          })
        })
      })
    });
  }

The data is showing up in the Ember inspector. I see the network calls. I even tried hardcoding/unserializing field1 to some static text in a custom serializer. No matter what I do, I cannot get the data to show up in the template. It seems like it’s loaded in ember data, but when I try to get it, it is undefined.

I’d love any suggestions anyone might have.


#2

Got it. So, it would appear that with ember-data 2.12.x, a very subtle change was made regarding serializers and the JSONAPI spec.

I have a custom serializer/adapter and a funky API to match it. So I have my own base serializer that handles the funkiness. I used to be able to do something like this in my serializer to map relationships…

    normalized.data.relationships = {
      books: {
        data: data.bookIds.map((bookId) => {
          return { id: bookId, type: 'authorBook' };
        })
      }
    };

With ember-data 2.12.x I have to do this.

    normalized.data.relationships = {
      books: {
        data: data.bookIds.map((bookId) => {
          return { id: bookId, type: 'author-book' };
        })
      }
    };

Camel-cased is no longer valid for type. The type must be dasherized and contain a hyphen for multi-word types. I made a Twiddle to better illustrate this.

:joy::cry: I had to tear down my app and delete just about everything until I could figure this out. That was very subtle and kind of awful to debug, but at least it’s working now!


#3

:clap: Well-done. That is indeed a nightmare.