我正在为DreamFactory服务平台编写一个 Ember 数据适配器,并且遇到了一个问题,我认为与我的适配器有关。
更新现有记录时,由model.save()
产生的promise会被拒绝,但会出现错误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
问题是-对REST API的请求和从REST API返回的响应具有相同的ID!
请求(PUT){ "record": { "id": "1", "title": "Sample Event", "date": "7/20/2013", "type": "success", "desc": "My first sample event." }}
响应{ "record": [ { "id": 1, "title": "Sample Event", "date": "7/20/2013", "type": "success", "desc": "My first sample event." } ]}
真正奇怪的是,记录仍然在数据库中的和商店中正确更新!
我在http://emberjs.jsbin.com/mosek/1/edit上有一个正在工作的JSBin,可以说明问题。我的自定义适配器在GitHub上的https://github.com/ultimatemonty/ember-data-dreamfactory-adapter上。 JSBin和我的应用程序都使用Ember 1.7.0和ED 1.0.0-beta.9
编辑
JSBin附加到我个人托管的DreamFactory实例上-在允许从JSBin进行访问之外,我没有做任何事情,但是请保持谨慎:)
*编辑#2 *
可以在GitHub上的https://github.com/ultimatemonty/ember-data-dreamfactory-adapter/blob/master/lib/ember-data-dreamfactory-adapter.js#L106上访问updateRecord
代码,但这是完整的参考方法:
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);
});
});
}
最佳答案
您使用的适配器/序列化器期望您返回一个没有类型的响应:
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
示例:http://emberjs.jsbin.com/tigiza/1/edit
您可以在
extractSingle
中看到它,它尝试将有效负载包装在具有指定类型的另一个对象中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);
},
您的回复如下所示:
{
"record": [
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
]
}
然后序列化器启动,看起来像这样:
{
event:{
"record": [
{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
]
}
}
实际上,序列化器应具有以下外观:
{
event:{
"id": 1,
"title": "Sample Event",
"date": "7/20/2013",
"type": "success",
"desc": "My first sample event."
}
}
您可以从第二个示例中看到,序列化程序将其包装在类型中,然后Ember Data说,嘿,给我id,所以它查看 undefined 的
event.id
,因为它位于event.record[0].id
下