0

I'm having an issue with Ember-Data transactions.

I have a DS.Model like so

App.MyModel = DS.Model.extend({
    id: DS.attr(),
    answers: DS.hasMany('App.Answer') // another model 
});

Then it is initiated later like so, in the a Route

model: function(){
     var transaction = this.get('store').transaction();

     return transaction.createRecord(App.MyModel, {
         id: '1'
     });
}

I have a Model that makes a request to my back end server using transaction and commit.

this.get('content.transaction').commit();

With the intent that answers is updated on the server side and sent back to me. If the content hasn't been updated yet, I call this

this.get('content').reload();

And the request is sent again.

This all works fine. answers gets populated if the id is found.

My issue is that occasionally, depending on what I get back from the server, I have to make another server request. The initial request works fine with

this.get('content.transaction').commit();

but when I try to reload the transaction, I get an error, as follows

Uncaught Error: Attempted to handle event `loadedData` on <App.Answer> while in state rootState.loaded.updated.uncommitted. Called with undefined

Now when I remove the reload, I no longer get the error, also when I check the console of Chrome under the network tab, I can see that the results I want are being sent back but they are not being updated in my DS Model. answers is left undefined.

Anyone know why this is happening? Am I using the transactions wrong?

EDIT

Application.SearchController = Ember.ObjectController.extend({
    isComplete: function () {
        return this.get('content.answers.length') !== 0;
    },


    search: function () {
        this.get('content.transaction').commit();

        var record = this.get('content');

        var interval = setInterval(function (controller) {
            if (controller.get('isComplete')) {
                controller.transitionToRoute("search.view");
                clearInterval(interval);
            } else {
                record.reload();
            }
        }, 5000, this);
    }
 });

SO basically some work in done in my route to set up my models and set them to the content, the model has an id that will be used on the server side and sent back with the results of the search then added to "answers".

This work fine until there are multiple results are found. Then a new model is created and the search function is called again on a different controller, with different content. This time round on the line record.reload();

I get the error Uncaught Error: Attempted to handle event loadedData on while in state rootState.loaded.updated.uncommitted. Called with undefined

So the server still responds with the correct results but the "answers" is not updated on the client side.

johnjo
  • 1,785
  • 1
  • 11
  • 11

2 Answers2

0

Your MyModel record is locally modified (client side). Calling reload will try to update it, which is prohibited in the current state of the record.

You can check this with a command:

console.log( this.get('content.stateManager.currentState.path') );
this.get('content').reload();

This should display in your console that the record is in the uncommitted state.

UPDATE:

You can't use a timer. Everything is asynchronous and you have no guarantee that your model will be updated during that interval. Which means that while you commit your record, you may reload it at the same time (this would generate the error you see).

What you want is something like that:

Application.SearchController = Ember.ObjectController.extend({
    search: function () {
        var record = this.get('content'),
            controller = this;

        record.one('didCommit', function() {
            controller.transitionToRoute("search.view"); 
        });

        record.transaction.commit();
    }
});
Cyril Fluck
  • 1,561
  • 7
  • 9
  • I've come to that conclusion myself. The error message basically tells me. Any ideas of a solution to this issue, am I using the transaction right? – johnjo Apr 30 '13 at 22:32
  • There's not enough of your code here to be able to point out the real issue. I don't know what you do in your app to modify a `App.MyModel` record. The logic that you use to call `reload` after `commit` seems dangerous. – Cyril Fluck May 01 '13 at 01:19
  • I had to use an interval as doing it this way, the server was just being rammed with requests – johnjo May 02 '13 at 10:27
  • A search ALWAYS has an answer? Is the search asynchronous on the backend? – Cyril Fluck May 02 '13 at 15:06
0

After the first commit the transaction is placed on the default transaction.

Error Attempted to handle event `loadedData` : Object not updated after deleteRecord

And remember always setup the router first.

Community
  • 1
  • 1
Ben Crowhurst
  • 8,204
  • 6
  • 48
  • 78