Sproutcore数据源和模型关系

时间:2011-06-28 09:20:42

标签: datasource models sproutcore

我目前有一个Sproutcore应用程序设置,我的模型上有以下关系:

App.Client = SC.Record.extend({
    name: SC.Record.attr(String),
    brands: SC.Record.toMany('App.Brand', {isMaster: YES, inverse: 'client'})
});

App.Brand = SC.Record.extend({
    name: SC.Record.attr(String),
    client: SC.Record.toOne('App.Client, {isMaster: NO, inverse: 'brands'})
});

当我使用灯具时,我的客户夹具看起来像这样:

{
    guid: 1,
    name: 'My client',
    brands: [1, 2]
}

我对品牌的固定看起来像这样:

{
    guid: 1,
    name: 'My brand',
    client: 1
}

对于我来说,获得客户品牌和获得品牌客户一切都很顺利。 我的问题是关于Datasources如何适应这个以及如何格式化服务器响应。

  1. 从服务器返回的数据是否应该完全符合fixtures文件的格式?那么客户应该始终包含一个包含一系列品牌ID的品牌属性?反之亦然。

  2. 如果我有一个源列表视图,显示其下面有品牌的客户已分组。我如何使用我的数据源为源视图加载数据?我应该打电话给服务器以获取所有客户端,然后通过电话获取所有品牌来跟进吗?

  3. 由于

    标记

1 个答案:

答案 0 :(得分:2)

你返回的json将主要镜像灯具。我最近和你有同样的问题,所以我在Grails中构建了一个后端,在SC中构建了一个前端,只是为了探索商店和数据源。我的模特是:

Scds.Project = SC.Record.extend(
    /** @scope Scds.Project.prototype */ {
      primaryKey: 'id',
      name: SC.Record.attr(String),
      tasks: SC.Record.toMany("Scds.Task", {
            isMaster: YES,
            inverse: 'project'
          })
    });


Scds.Task = SC.Record.extend(
    /** @scope Scds.Task.prototype */ {

      name: SC.Record.attr(String),
      project: SC.Record.toOne("Scds.Project", {
            isMaster: NO
          })

    });

为项目返回的json是

[{"id":1,"name":"Project 1","tasks":[1,2,3,4,5]},{"id":2,"name":"Project 2","tasks":[6,7,8]}]
当我选择一个项目时,

和json返回的任务是

{"id":1,"name":"task 1"}
显然,这只是1个任务的json。如果你查看项目json,你会看到我把一个带有id的“任务”数组 - 这就是内部人员知道要获得哪些任务。所以要回答你的第一个问题,你不需要从孩子到父母的id,你需要父母加载所有孩子,所以json与灯具完全不匹配。

现在,它有点棘手。当我加载应用程序时,我会进行查询以获取所有项目。商店在数据源上调用fetch方法。这是我的实施。

Scds.PROJECTS_QUERY = SC.Query.local(Scds.Project);
var projects = Scds.store.find(Scds.PROJECTS_QUERY);
...


fetch: function(store, query) {
        console.log('fetch called');

        if (query === Scds.PROJECTS_QUERY) {
          console.log('fetch projects');
          SC.Request.getUrl('scds/project/list').json().
              notify(this, '_projectsLoaded', store, query).
              send();

        } else if (query === Scds.TASKS_QUERY) {
          console.log('tasks query');
        }

        return YES; // return YES if you handled the query
      },

      _projectsLoaded: function(response, store, query) {
        console.log('projects loaded....');

        if (SC.ok(response)) {
          var recordType = query.get('recordType'),
              records = response.get('body');

          store.loadRecords(recordType, records);
          store.dataSourceDidFetchQuery(query);

          Scds.Statechart.sendEvent('projectsLoaded')
        } else {
          console.log('oops...error loading projects');
          // Tell the store that your server returned an error
          store.dataSourceDidErrorQuery(query, response);
        }
      }

这将获得项目,但不是任务。 Sproutcore知道,只要我访问Project上的tasks数组,它就需要获取它们。它的作用是在数据源中调用retrieveRecords。该方法依次为任务数组中的每个id调用retrieveRecord。我的retrieveRecord方法看起来像

retrieveRecord: function(store, storeKey) {
        var id = Scds.store.idFor(storeKey);
        console.log('retrieveRecord called with [storeKey, id] [%@, %@]'.fmt(storeKey, id));

        SC.Request.getUrl('scds/task/get/%@'.fmt(id)).json().
            notify(this, "_didRetrieveRecord", store, storeKey).
            send();

        return YES;
      },

      _didRetrieveRecord: function(response, store, storeKey) {
        if (SC.ok(response)) {
          console.log('succesfully loaded task %@'.fmt(response.get('body')));
          var dataHash = response.get('body');
          store.dataSourceDidComplete(storeKey, dataHash);

        } ...
      },

请注意,您应该使用sc-gen来生成数据源,因为它提供了一个相当好的刷新存根,可以指导您实现所需的方法。它不提供retrieveMethods实现,但如果您不想为要加载的每个子记录执行单个请求,则可以提供自己的实现。

请注意,您始终拥有选项。如果我想,我可以创建一个Tasks查询并预先加载所有任务数据,这样我点击一个项目时就不需要去我的服务器了。所以在回答你的第二个问题时,这取决于你。您可以在单击客户端时加载品牌,也可以预先加载所有数据,如果没有那么多数据,这可能是个好主意。