getoutreach / epf

A framework for keeping your Ember.js apps in sync.
http://epf.io
MIT License
369 stars 33 forks source link

created model overwrites subsequent changes #64

Closed lastobelus closed 10 years ago

lastobelus commented 11 years ago

My app is setup to create a new model once it has data in a textfield, and to autosave changes. I accomplish this by using Ember.run.debounce to flush the session.

I am passing through clientId and clientRev.

When I start typing in the text field, a new record is created. When the create finishes, epf overwrites subsequent changes -- so everything typed after the create gets fired gets deleted. It's easy to make the problem very obvious by adding a couple second delay on the backend.

I have tried using a child session or not, it doesn't seem to make a difference.

Update seems to work fine, although I'm confused how, since client_id & client_rev aren't passed through on updates.

lastobelus commented 11 years ago

I forgot to mention that the way I defer creation of the model is to create a detached model, with App.Model.create and call session.add(model) when it has data and should be persisted.

lastobelus commented 11 years ago

I was able to get this to work by doing my own merge as below, but it seems ugly. I'd like to find out why merging is not working on create. As far as I can tell by looking at the code, both create and update call processData on the returned model. I haven't dug more deeply than that. Merging is working with updates for me.


if(model.get('isDetached') && !model.get('isCreating')){
  var created = session.create('model', {text: model.get('text')});
  var thisController = this;
  session.flush().then(function(){
    created.set('text', model.get('text'));
    thisController.set('model', created);
  })
  model.set('isCreating', true);
  model.set('isDirty', false); # necessary because this is in an observer that observes multiple properties
} else {
  this.save(); // this calls session.flush through debounce
}
lastobelus commented 11 years ago

my workaround is not going to work in the long-run, as it means display of the model in other areas of the app do not update while the model is being created, which is essential.

ghempton commented 11 years ago

Hmm this should definitely work out of the box... I will try and reproduce this and fix (first step is to get a test)

lastobelus commented 11 years ago

I have a deadline for tues. noon, but if things go well I will try to write a test before then or else the day after. I did get my autosave working, although it is kinda ugly. Basically, I maintain a dictionary of pending models and keep them in sync with a model that is backing the interface.

Here is a distillation that reproduces the problem:

var widget = Session.create('widget')
widget.set('text', 'bob');
session.flush();
widget.set('text', 'bobandmary');
session.flush();
// POST called. PUT never called. widget.text is 'bob' after POST finishes.

I tried to trace through and understand the problem, but the code was a little beyond my being able to understand in a couple hours, lol. I'm quite impressed by epf. But I think the root of the problem is that the clientId doesn't get set on widget, but only on the copy of it used by the create operation.

ghempton commented 10 years ago

I am going to close this until we can get a test case.