3

Lets say I have two models, Book and Chapter.

App.Book = DS.Model.extend
  name: DS.attr 'string'
  chapters: DS.hasMany 'chapters', async: true

App.Chapter = DS.Model.extend
  name: DS.attr 'string'
  book: DS.belongsTo 'book', async: true

Using emberFire.

App.ApplicationAdapter = DS.FirebaseAdapter.extend
  firebase: new Firebase('http://<my-firebase>.firebaseio.com/')

App.ApplicationSerializer = DS.FirebaseSerializer.extend()

According to the documentation on relationships, using the async: true option, Firebase would expect my data to look something like the following.

{
  'books': [{
    'book_id_1': {
      'name': 'Example',
      'chapters': [{
        'chapter_id_1': true
      }]
  }],
  'chapters': [{
    'chapter_id_1': {
      'name': 'Chapter 1'
    }
  }]
}

I can save a Chapter just fine, however I can't seem to get the chapters property of a Book populated with a newly created Chapter.

In the chrome console:

var store = App.__container__.lookup('store:main')
store.find('book', 'book_id_1').then(function(b) { window.book = b });

var chapter = store.createRecord('chapter', { name: 'Chapter 1' });

chapter.save().then(function() {  // Saves the chapter
  book.get('chapters').then(function(chapters) {
    chapters.addObject(chapter);
    book.save();  // Doesn't append to the chapters object
  }
});

The above code does not save the chapters property on the book the way I would expect it to. Any help would be appreciated.


EDIT

It looks like the proper way to add the chapter object to the book.chapters property is:

book.get('chapters').then(function(chapters) {
  chapters.addObject(chapter);
  book.save().then(function() {
    chapter.save();
  });
});

But if there are validation errors on the chapter object, it will be added to the book.chapters property but won't be saved (creating an invalid reference). How do you get around this?

Feech
  • 4,072
  • 4
  • 28
  • 36

1 Answers1

2

Ember-Data has a weird nuance where if something is defined from one relationship as a hasMany and the corresponding record as a belongsTo it only sends up the attribute if it's the belongsTo. That being said, you'd need to call chapter.save(). I actually hate this, and I've complained about it before, but I've been to lazy to submit a pull request.

Kingpin2k
  • 47,277
  • 10
  • 78
  • 96
  • I'm not sure I completely understand what you mean. Removing the `belongsTo` and rearranging my `save()` calls (ie, first saving the `book` after the chapter is added, *then* saving the `chapter`) fixes the issue, but I have no idea why. Can you elaborate? – Feech Apr 05 '14 at 15:06
  • I'm curious why removing the `belongsTo` from the `Chapter` model partially fixes the issue.. – Feech Apr 06 '14 at 17:56
  • It's related to how ED decides to serialize a hasMany relationship. It does it different depending on the corresponding record, you can see me asking about it in the code here, https://github.com/emberjs/data/commit/7f752ad15eb9b9454e3da3f4e0b8c487cdc70ff0#commitcomment-4923439 – Kingpin2k Apr 06 '14 at 18:20