访问在json服务器响应中传递的元信息

时间:2013-01-14 16:54:55

标签: ember.js ember-data

我正在使用Ember-Data Rest-Adapter,从我的服务器返回的JSON看起来基本上与Active Model Serializers Documentation

中的JSON相似
{
  "meta": { "total": 10 },
  "posts": [
    { "title": "Post 1", "body": "Hello!" },
    { "title": "Post 2", "body": "Goodbye!" }
  ]
}

从服务器获取数据有效,但遗憾的是我无法确定从JSON响应中访问元信息的位置。

根据我对ember-data的github问题的研究,对meta信息的支持似乎是implemented,提交1787bff

但即使有测试用例,我也无法弄清楚如何访问元信息。

App.PostController = Ember.ArrayController.extend({
   ....
   requestSearchData: function(searchParams){
      posts = App.Post.find(searchParams);
      this.set('content', posts);
      // don't know how to access meta["total"]
      // but I want to do something like this:
      // this.set('totalCount', meta["total"])
   }
})

你们中的任何人都可以为我解释这个问题吗?我知道Ember api正在快速移动,但我确信我只是错过了一小部分而且这实际上是可能的。

3 个答案:

答案 0 :(得分:7)

我找到了一种更清晰的方法,用于使用ember-data从服务器响应中提取元信息。

我们必须告诉序列化器期望哪些元信息(在这种情况下是分页):

 App.serializer = DS.RESTSerializer.create();

 App.serializer.configure({ pagination: 'pagination' });

 App.CustomAdapter = DS.RESTAdapter.extend({
   serializer: App.serializer
 });

 App.Store = DS.Store.extend({
   adapter: 'App.CustomAdapter'
 });

之后,每次服务器发送带有分页对象的元属性时,此对象将被添加到商店的TypeMaps属性中,以用于请求的Model-Class。

例如,有以下回复:

  {
    'meta': {'pagination': { 'page': 1, 'total': 10 } },
    'posts':[
      ...
    ]
  }

App.Post-Model的TypeMap将包含帖子加载后的分页对象。

您无法直接观察商店的TypeMaps属性,因此我将一个计算属性添加到PostsController以访问请求分页元信息:

 App.PostsController = Ember.ArrayController.extend({
    pagination: function () {
      if (this.get('model.isLoaded')) {
        modelType = this.get('model.type');
        this.get('store').typeMapFor(modelType).metadata.pagination
      }
    }.property('model.isLoaded')
 });

我真的不认为这是元信息问题的一个很好的解决方案,但这是我能够用Ember-Data提出的最佳解决方案。也许这将来会更容易。

答案 1 :(得分:6)

我找到了一种方法来访问响应中传递的元信息。但遗憾的是,它似乎并没有得到开箱即用的ember-data的支持,我正在将元信息写入一个全局变量,然后我通过请求控制器中的绑定进行访问。

我最终自定义了RESTAdapter正在使用的序列化程序:

App.CustomRESTSerializer = DS.RESTSerializer.extend({
  extractMeta: function(loader, type, json) {
    var meta;
    meta = json[this.configOption(type, 'meta')];
    if (!meta) { return; }
    Ember.set('App.metaDataForLastRequest', meta);
    this._super(loader, type, json);
  }
});

App.Store = DS.Store.extend({
  revision: 11,
  adapter: DS.RESTAdapter.create({
    bulkCommit: false,
    serializer: App.CustomRESTSerializer
  })
});

我知道这并不是特别漂亮,并且实际上认为这与ember-data期望我们做的事情相反,但暂时它正常工作。

我会尝试以更好的方式使用ember-data,并在工作时提交拉取请求,或者在任何其他人有兴趣使用此工作时在github上打开问题。

如果有人找到更清洁的解决方案,请告诉我。

答案 2 :(得分:2)

我认为您的直接修复方法是将totalCount附加到您的模型(recordArray),请参阅此thread

另一种方法是创建自己的适配器:

DS.Adapter.create({
  find: function (store, type, id) {
    $.ajax({
      url:      type.url,
      dataType: 'jsonp',
      context:  store,
      success:  function(response){
        this.load(type, id, response.data);
      }
    });
  },
  findAll: function(store, type) {
    $.ajax({
      url:      type.url,
      dataType: 'jsonp',
      context:  store,
      success:  function(response){
        this.loadMany(type, response.data);
      }
    });
  }
});

findAll方法中成功回调的响应参数应该是您需要的对象:

response: {
  meta: {
    totalCount: 10
  },
  posts: [{}, {}]
}

希望这有帮助。