Search code examples
ember.jsember-app-kit

Ember-data failing to load relationships


I'm having trouble loading some related models with ember-data. I'm pretty sure this is a syntax error on my part, but I just can't see it. Perhaps someone could be a second set of eyes for me?

The specific problem is that related models are not being displayed in my template.

Without further ado:

Notes

  • I'm using ember-appkit-rails.
  • This is my first ember project, so please forgive my n00bness.
  • I have a feeling that the answer may have something to do with embedded: 'always', but I have no idea how to integrate that into my code.
  • DEBUG: Ember : 1.4.0 ember.js?body=1:3462
  • DEBUG: Ember Data : 1.0.0-beta.7+canary.f482da04 ember.js?body=1:3462
  • DEBUG: Handlebars : 1.3.0 ember.js?body=1:3462
  • DEBUG: jQuery : 1.11.0 ember.js?body=1:3462

The problematic template

I'd think that this should work. It's almost right out of the ember-appkit-rails generators. The librettist and composer names are not appearing.

<h3>{{id}}</h3>

<p>{{link-to 'Edit' 'operas.edit' this}} <button {{action destroyRecord this}}>Destroy</button></p>

<ul>
  <li>Title: {{title}}</li>
  <li>Alternate Title: {{alternate_title}}</li>
  <li>Source: {{source}}</li>
  <li>Librettist: {{librettist.name}}</li>
  <li>Composer: {{composer.name}}</li>
  <li>Notes: {{notes}}</li>
</ul>

Models

opera.js.es6

export default DS.Model.extend({
  title: DS.attr('string'),
  alternateTitle: DS.attr('string'),
  source: DS.attr('string'),
  librettistId: DS.attr('number'),
  composerId: DS.attr('number'),
  notes: DS.attr('string'),
  composer: DS.belongsTo('composer'),
  librettist: DS.belongsTo('librettist')
});

librettist.js.es6

export default DS.Model.extend({
  name: DS.attr('string'),
  operas: DS.hasMany('opera')
});

composer.js.es6

export default DS.Model.extend({
  name: DS.attr('string'),
  operas: DS.hasMany('opera')
});

ActiveModel Serializer

class OperaSerializer < ActiveModel::Serializer
  embed :ids, include: true

  attributes :id, :title, :alternate_title, :source, :librettist_id, :composer_id, :notes
  has_one :composer
  has_one :librettist
end

Sample JSON being returned

This is what I see when I look at one opera record, but the structure holds for the entire set:

{
  "composers": [
    {
      "id": 4097,
      "name": "Müller, Wenzel"
    }
  ],
  "librettists": [
    {
      "id": 1414,
      "name": "Bäuerle, Adolf"
    }
  ],
  "opera": {
    "alternate_title": "oder Wien in einem anderen Weltteile",
    "composer_id": 4097,
    "id": 4166,
    "librettist_id": 1414,
    "notes": "these are some notes",
    "source": "F116.Theater.a.d.Wien.260A.Mus; Mus.Hs.78.Mus; Mus.Hs.25409.Mus",
    "title": "Aline Königin von Golkonda"
  }
}

I've also tried this approach with inline embedding ({opera: {...composer: {...}}}) but that didn't work any better.

Thanks for your help! Paul.


Solution

  • the _id are not necessary if you're using the RESTAdapter as your client-side adapter.

    App.Opera = DS.Model.extend({
      title: DS.attr('string'),
      alternateTitle: DS.attr('string'),
      source: DS.attr('string'),
      notes: DS.attr('string'),
      composer: DS.belongsTo('composer'),
      librettist: DS.belongsTo('librettist')
    });
    
    App.Librettist = DS.Model.extend({
      name: DS.attr('string'),
      operas: DS.hasMany('opera')
    });
    
    App.Composer = DS.Model.extend({
      name: DS.attr('string'),
      operas: DS.hasMany('opera')
    });
    

    JSON

    {
      "composers": [
        {
          "id": 4097,
          "name": "Müller, Wenzel"
        }
      ],
      "librettists": [
        {
          "id": 1414,
          "name": "Bäuerle, Adolf"
        }
      ],
      "opera": {
        "alternate_title": "oder Wien in einem anderen Weltteile",
        "composer": 4097,
        "id": 4166,
        "librettist": 1414,
        "notes": "these are some notes",
        "source": "F116.Theater.a.d.Wien.260A.Mus; Mus.Hs.78.Mus; Mus.Hs.25409.Mus",
        "title": "Aline Königin von Golkonda"
      }
    }
    

    http://emberjs.jsbin.com/OxIDiVU/233/edit

    If you're using the ActiveModelAdapter then you'd use the _id in the json, here's an example with the ActiveModelAdapter

    http://emberjs.jsbin.com/OxIDiVU/234/edit