我有一个带有产品型号的Ember应用程序。我的服务器响应是这样的json(对于一个条目)
{
"id": "a01dfaa0",
"type": "computer",
"cost": "0.50"
}
或此类对象的数组
[{
"id": "6b2360d0",
"type": "fridge",
"cost": "2.50"
},{
"id": "a01dfaa1",
"type": "car",
"cost": "5.95"
}]
换句话说,没有顶级命名空间(基于模型名称),Ember期望。当我将数据返回到Ember应用程序时,我知道我可以通过extractArray函数运行它来添加该命名空间(我假设的“产品”或“产品”)但我无法弄清楚如何做到这一点。问题:我该怎么做
extractArray: function(store, type, payload) {
}
更新,如果我使用第一个答案提出的方法,即把它放在我的DS.RESTSerializer中
// Override
extractArray(store, type, payload) {
payload = this._extractPayload(Ember.String.pluralize(type.typeKey), payload);
return this._super(store, type, payload);
},
// Override
extractSingle(store, type, payload, id) {
payload = this._extractPayload(type.typeKey, payload);
return this._super(store, type, payload, id);
},
_extractPayload(typeKey, payload) {
var conformPayload = {};
if (payload) {
conformPayload[typeKey] = payload;
}
return conformPayload;
}
当我的服务器以空数组响应时,出现错误。当没有记录时,Ember通常期望这个{products : [] }
,所以当没有记录时我返回[]
,但是使用上面的extractArray方法,它会抛出一个错误,说response from findAll must be an array, not undefined Error
。当我在extractArray函数中执行console.log(payload)
时,它会显示一个空数组[]
。问题,如何在RESTSerializer中修改Ember,以便它可以在没有顶层命名空间的情况下使用json,并且,如果在数据库中没有记录时它不应该接收空数组[]
,那么什么是它应该收到?
注意,由于服务器期望json没有顶层命名空间,因此II通过RestAdapter的serializeIntoHash函数将其发送到服务器,以从json中删除命名空间(typekey)(但我无法弄清楚如何将它添加回extractArray函数中)
serializeIntoHash: function( hash, type, record, options ) {
console.log(hash, type, record, options, "h,t,r,o");
// Usergrid does not expect a type-key
record.eachAttribute(function( name, meta ) {
hash[name] = record.get(name);
});
return hash;
}
更新 这是我在运行任何建议的答案时得到的错误的堆栈跟踪
Error while processing route: gopher Assertion Failed: The response from a findAll must be an Array, not undefined Error: Assertion Failed: The response from a findAll must be an Array, not undefined
at new Error (native)
at Error.EmberError (http://localhost:8080/js/vendor.js:22707:21)
at Object.Ember.default.assert (http://localhost:8080/js/vendor.js:15408:13)
at http://localhost:8080/js/vendor.js:64040:17
at Object.Backburner.run (http://localhost:8080/js/vendor.js:10778:27)
at ember$data$lib$system$store$$Service.extend._adapterRun (http://localhost:8080/js/vendor.js:70295:33)
at http://localhost:8080/js/vendor.js:64037:15
at tryCatch (http://localhost:8080/js/vendor.js:55993:16)
at invokeCallback (http://localhost:8080/js/vendor.js:56005:17)
at publish (http://localhost:8080/js/vendor.js:55976:11)
更新。这是完整的适配器和序列化程序代码(我没有使用Ember-Cli)
App.ApplicationAdapter = DS.RESTAdapter.extend({
});
// Must extend REST serializer to handle Usergrid JSON format, which is
// different from what Ember-Data expects.
App.ApplicationSerializer = DS.RESTSerializer.extend({
extractSingle: function(store, type, payload, id) {
var convertedPayload = {};
convertedPayload[type.modelName] = payload;
return this._super(store, type, convertedPayload, id);
},
extractArray: function(store, type, payload) {
console.log(payload, "payload");
var convertedPayload = {};
convertedPayload[type.modelName] = payload;
return this._super(store, type, convertedPayload);
},
});
答案 0 :(得分:2)
您可以使用typeKey创建一个ember数据符合有效负载,如下所示:
在ember数据beta 18(http://emberjs.com/blog/2015/05/21/ember-data-1-0-beta-18-released.html)中使用type.modelName而不是type.typeKey
// Override
extractArray(store, type, payload) {
payload = this._extractPayload(Ember.String.pluralize(type.typeKey), payload);
return this._super(store, type, payload);
},
// Override
extractSingle(store, type, payload, id) {
payload = this._extractPayload(type.typeKey, payload);
return this._super(store, type, payload, id);
},
_extractPayload(typeKey, payload) {
var conformPayload = {};
if (payload) {
conformPayload[typeKey] = payload;
}
return conformPayload;
}
答案 1 :(得分:2)
我建议在适配器上定义自己的find
。它会进行ajax调用并将有效负载推送到商店。请参阅http://emberjs.com/api/data/classes/DS.Adapter.html#method_find。
以下使用fetch
(如果您愿意,请替换为$.ajax
。)
// adapters/product.js
...
find(store, type, id, snapshot) {
function get() { return fetch(url); }
function json(response) { return response.json(); }
function push(json) { return store.pushPayload({ products: json }); }
var url = this.buildURL ('product', id);
return get() . then(json) . then(push);
}
使用this.buildURL
可确保正确构建URL,包括命名空间,复数等。
覆盖extractArray
及其朋友不是太有趣,而且容易出错。我会为棘手的案件保留这种方法。
要返回服务器,使用serializeIntoHash
很好,但以下内容会更加紧凑和强大:
// app/serializers/product.js
serializeIntoHash: function(data, type, record, options) {
Ember.merge(data, this.serialize(record, options));
}
答案 2 :(得分:1)
modelName
)serializeIntoHash: function(hash, type, snapshot, options) {
Ember.merge(hash, this.serialize(snapshot, options));
},
extractSingle: function(store, type, payload, id) {
var convertedPayload = {};
convertedPayload[type.modelName] = payload;
return this._super(store, type, convertedPayload, id);
},
extractArray: function(store, type, payload) {
var convertedPayload = {};
convertedPayload[type.modelName] = payload;
return this._super(store, type, convertedPayload);
}
这是一个有效的JSBin,用于演示:http://jsbin.com/bebori/1/edit?js,output
typeKey
)serializeIntoHash: function(hash, type, snapshot, options) {
Ember.merge(hash, this.serialize(snapshot, options));
},
extractSingle: function(store, type, payload, id) {
var convertedPayload = {};
convertedPayload[type.typeKey] = payload;
return this._super(store, type, convertedPayload, id);
},
extractArray: function(store, type, payload) {
var convertedPayload = {};
convertedPayload[type.typeKe] = payload;
return this._super(store, type, convertedPayload);
}
这是一个有效的JSBin,用于演示:http://jsbin.com/hanuwa/1/edit?js,output
我认为与其他答案看起来非常相似的问题是使用Ember.String.pluralize
- 我不认为应该在那里。