【问题标题】:Sproutcore datasources and model relationshipsSproutcore 数据源和模型关系
【发布时间】:2011-06-28 09:20:41
【问题描述】:

我目前有一个 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
}

这对我获得客户品牌和获得品牌客户来说都很好。 我的问题是关于数据源如何适应这一点以及服务器响应应该如何格式化。

  1. 从服务器返回的数据是否应该与夹具文件的格式完全一致?所以客户应该总是包含一个包含一系列品牌 ID 的品牌属性?反之亦然。

  2. 如果我有一个源列表视图,该视图显示客户及其下方的品牌分组。我将如何使用我的数据源为源视图加载该数据?我是否应该调用服务器以获取所有客户端,然后调用以获取所有品牌?

谢谢

标记

【问题讨论】:

    标签: datasource models sproutcore


    【解决方案1】:

    您返回的 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 知道,只要我访问项目上的任务数组,它就需要获取它们。它的作用是在数据源中调用retrieveRecords。该方法依次为 tasks 数组中的每个 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 实现,但如果您不想为正在加载的每个子记录执行单个请求,您可以提供自己的实现。

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

    【讨论】:

    • 请原谅我的入侵,但我一直在研究 sproutcore 并将其绑定到一个真正的后端数据源中。我是否了解您正在访问的 URI(例如“scds/project/list”)在 Grails 中? -谢谢
    • @johnO,是的圣杯。但是应用程序的后端可以是任何东西,java、nodejs、php、rails 等等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2016-05-10
    相关资源
    最近更新 更多