Search code examples
ember.jsember-dataemberfire

Saving Ember-Data records


Questions:

  1. This line of code _activeAuthor.get('books').pushObject(book).save(); is processed without error in Chrome but the book is not added to the books property of the _activeAuthor instance of Ember-Data. I don't understand why?
  2. The below code add the created Book to the Book property of the Chapter instance (see comment). It is a one-to-many relationship (see de Models). Ember-Data seems to automatically populate the related record on the Book instance. Is this a normal behaviour of Ember-Data? Should I let Ember-Data populate the related side of a relationship one-to-many or should I specify both sides and persist both instances?
  3. I suspect that one of the issue of the below code is that the I do not handle promises properly. This code: this.modelFor('user').get('latestChapter'); seems to return a promise. How should I handle promisses with get()?

Code:

createChapter: function() {
  //Getting the Author of the latestChapter or getting the first Author in the array
  var _activeAuthor = null;
  var authors = this.modelFor('user').get('authors').toArray();
  var latestChapter = this.modelFor('user').get('latestChapter');
  var latestAuthor = latestChapter.get('author');
  if (latestChapter.content) {
    _activeAuthor = latestAuthor;
  } else {
    _activeAuthor= authors[0];
  }

  var book = this.store.createRecord('book', {
    title: 'click here to name your book',
    author: _activeAuthor,
  });

  var chapter = this.store.createRecord('chapter', {
    title: 'Click here to name your chapter',
    book: book, // Add the created Book to the Book property of the Chapter instance
  });

  _activeAuthor.get('books').pushObject(book).save();
  chapter.save();
  book.save();
  this.modelFor('user').set('latestChapter', chapter).save() //Identifying the latest created chapter at the lastestChapter;
  console.log('New chapter created: ' + chapter.get('id'));
},

Models:

App.Author = DS.Model.extend({
  type: DS.attr('string'),
  authorTitle: DS.attr('string'),
  userTitle: DS.attr('string'),
  description: DS.attr('string'),
  user: DS.belongsTo('user', {inverse: 'authors', async: true}),
  books: DS.hasMany('book', { inverse: 'author', async: true}),
});


App.Book = DS.Model.extend({
  title: DS.attr('string'),
  icon: DS.attr('string'),
  description: DS.attr('string'),
  frequency: DS.attr('string'),
  chapters: DS.hasMany('chapter', { inverse: 'book', async: true}),
  author: DS.belongsTo('author', { inverse: 'books', async: true}),
});


App.Chapter = DS.Model.extend({
  title: DS.attr('string'),
  description: DS.attr('string'),
  frequency: DS.attr('string'),
  unit: DS.attr('string'),
  aggregationMode: DS.attr('string'),
  dashboard: DS.attr('boolean'),
  statData : DS.attr('array'),
  book: DS.belongsTo('book', { inverse: 'chapters', async: true}),
});

Thanks!


Solution

  • 1. author.get('books') will return a promise, so probably what you want to do is

    author.get('books').then(function(books) {
        books.pushObject(book)
    });
    author.save();
    

    If this is not an issue, could you give a jsfiddle with the whole app code? Then, it'll be easier to help! :)

    2. Every time you get a model's property that is async and is not isLoaded (not synced with server), ember will ask the server and yes, will populate the records in your store which is a desired behaviour :)

    3. If you have an async model property, then you always get a promise, so you should handle it in for example this way:

    chapter.get('book').then(function(book) {
      // here's a book
    });
    

    BTW var latestAuthor = latestChapter.get('author'); -> chapter doesn't have author property :)