2
votes

I'm using ember 1.0 and ember-data 1.0.0 beta 1. I have the following routes and controller to create and save simple notes ('AuthenticatedRoute' is just a custom made route for logged-in users):

App.Note = DS.Model.extend({
  title: DS.attr(),
  author: DS.attr(),
  body: DS.attr(),
  createdAt: DS.attr()
});


App.NotesRoute = App.AuthenticatedRoute.extend({
    model: function() { return this.store.find('note'); },
  });

App.NotesNewRoute = App.AuthenticatedRoute.extend({
    model: function() {
      return this.store.createRecord('note');
    }
  });

App.NotesNewController = Ember.ObjectController.extend({
    actions: {
      save: function() {
        var self = this, model = this.get('model');
        model.set('author', localStorage.username);
        model.set('createdAt', new Date());
        model.save().then(function() {
          self.get('target.router').transitionTo('notes.index');
        });
      }
    }
  });

When I save a new note everything works as expected. But when I navigate away from the notes route and then back into it, the notes list is populated with a duplicate entry. One entry has an id and can be edited, deleted etc, the other has all the data of the first entry except the id attribute is null. It seems to me ember-data keeps the newly created record (that hasn't been committed to the database and thus has no id yet) alive even when the record becomes committed but I am uncertain as to why. When I reload the page, the list is correctly displayed, no duplicates appear. What am I doing wrong?

For the record, I am using mongodb so I use a custom serializer to convert '_id' attributes to ember-data friendly 'id's, essentially copied from here:

  App.NoteSerializer = DS.RESTSerializer.extend({
    normalize: function(type, hash, property) {
      // normalize the '_id'
      var json = { id: hash._id };
      delete hash._id;

      // normalize the underscored properties
      for (var prop in hash) {
        json[prop.camelize()] = hash[prop];
      }

      // delegate to any type-specific normalizations
      return this._super(type, json, property);
    }  
  });

I should also mention that this problem existed in ember-data 0.13 as well.

2

2 Answers

4
votes

It was a stupid mistake in my RESTful server. I was responding to POST requests with a 204 (empty) response instead of what ember-data expected, that is a 201 ("created") response with the newly created record as the payload. This post made me realize it.

It would be nice though to include this information in the official REST adapter documentation.

0
votes

That is certainly strange behaviour indeed. Unfortunately I'm not able to explain why you're experiencing this, however:

You can use the willTransition callback in the actions object in your Route to ensure that when it is transitioned away from, if NotesNewController's content property is dirty (i.e. has not been persisted yet), it will have its transaction rolled back.

App.NotesNewRoute = App.AuthenticatedRoute.extend({
  model: function() {
    return this.store.createRecord('note');
  },
  actions: {
    willTransition: function (transition) {
      var model = this.controllerFor('notesNew').get('content');
      if (model.get('isDirty') === true) {
        model.get('transaction').rollback();
      }
      return this._super(transition);
    }
  }
});