在extractArray中添加toplevel json名称空间(或模型名称)

时间:2015-06-01 16:41:21

标签: ember.js ember-data

我有一个带有产品型号的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);
},


});

3 个答案:

答案 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)

Ember Data 1.0.0-beta.18及以上(使用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

Ember Data 1.0.0-beta.17及更低版本(使用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 - 我不认为应该在那里。