3
votes

I'm writing an ember-data adapter for the DreamFactory services platform and am running into an issue I think is related to my adapter.

When updating an existing record the promise resulting from model.save() is ALWAYS rejected with an error of

Assertion Failed: An adapter cannot assign a new id to a record that already has an id. <App.Event311:1> had id: 1 and you tried to update it with null. This likely happened because your server returned data in response to a find or update that had a different id than the one you sent

Thing is - the request to the REST API and the response back from the REST API have the same ID!

Request (PUT)

{ "record": { "id": "1", "title": "Sample Event", "date": "7/20/2013", "type": "success", "desc": "My first sample event." } }

Response

{ "record": [ { "id": 1, "title": "Sample Event", "date": "7/20/2013", "type": "success", "desc": "My first sample event." } ] }

The really weird thing is the record still updates properly both in the store AND in the database!

I have a working JSBin at http://emberjs.jsbin.com/mosek/1/edit that illustrates the problem. My custom adapter is on GitHub at https://github.com/ultimatemonty/ember-data-dreamfactory-adapter. The JSBin as well as my app are using Ember 1.7.0 and ED 1.0.0-beta.9

EDIT

The JSBin is attached to my personal hosted instance of DreamFactory - I haven't done anything with it outside of allowing access from JSBin but please be gentle :)

* EDIT #2 *

The updateRecord code is accessible on GitHub at https://github.com/ultimatemonty/ember-data-dreamfactory-adapter/blob/master/lib/ember-data-dreamfactory-adapter.js#L106 but here is the full method for reference:

updateRecord: function(store, type, record) {
    var data = {};
    var serializer = store.serializerFor(type.typeKey);
    serializer.serializeIntoHash(data, type, record);
    var adapter = this;

    return new Ember.RSVP.Promise(function(resolve, reject) {
        // hack to make DSP send back the full object
        adapter.ajax(adapter.buildURL(type.typeKey) + '?fields=*', "PUT", { data: data }).then(function(json){
            // if the request is a success we'll return the same data we passed in
            resolve(json);
        }, function(reason){
            reject(reason.responseJSON);
        });
    });
}
1
The error message says you cannot post with an id. Why don't you remove the id? Ember Data expects the server to assign it.user663031
@torazaburo this is an update to an existing model so I need the id to perform the update.ultimatemonty
Try unloading the record from your store after the ajax request.Hrishi
An update is a PUT, not a POST.user663031

1 Answers

3
votes

The adapter/serializer you're using is expecting you to return a response without the type in it:

{ 
    "id": 1,
    "title": "Sample Event",
    "date": "7/20/2013",
    "type": "success",
    "desc": "My first sample event."
}

Example: http://emberjs.jsbin.com/tigiza/1/edit

You can see it here in the extractSingle, where it tries to wrap the payload in in another object with the type specified

EmberDreamFactoryAdapter.Serializer = DS.RESTSerializer.extend({

    extractArray: function(store, primaryType, payload) {
        var namespacedPayload = {};
        namespacedPayload[Ember.String.pluralize(primaryType.typeKey)] = payload.record;
        return this._super(store, primaryType, namespacedPayload);
    },

    extractSingle: function (store, primaryType, payload, recordId) {
        var namespacedPayload = {};
        namespacedPayload[primaryType.typeKey] = payload;
        return this._super(store, primaryType, namespacedPayload, recordId);
    },

Your response looks like this:

{
    "record": [
        {
            "id": 1,
            "title": "Sample Event",
            "date": "7/20/2013",
            "type": "success",
            "desc": "My first sample event."
        }
    ]
}

Then the serializer kicks in, and it looks like this:

{
    event:{
       "record": [
          {
            "id": 1,
            "title": "Sample Event",
            "date": "7/20/2013",
            "type": "success",
            "desc": "My first sample event."
          }
      ]
   }
}

When really, the serializer should have it looking like this:

{ 
  event:{
    "id": 1,
    "title": "Sample Event",
    "date": "7/20/2013",
    "type": "success",
    "desc": "My first sample event."
  }
}

You can see from the second example, the serializer wraps it in the type, then Ember Data says, hey, give me the id, so it looks at event.id which is undefined, because it lives under event.record[0].id