我目前有一个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如何适应这个以及如何格式化服务器响应。
从服务器返回的数据是否应该完全符合fixtures文件的格式?那么客户应该始终包含一个包含一系列品牌ID的品牌属性?反之亦然。
如果我有一个源列表视图,显示其下面有品牌的客户已分组。我如何使用我的数据源为源视图加载数据?我应该打电话给服务器以获取所有客户端,然后通过电话获取所有品牌来跟进吗?
由于
标记
答案 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查询并预先加载所有任务数据,这样我点击一个项目时就不需要去我的服务器了。所以在回答你的第二个问题时,这取决于你。您可以在单击客户端时加载品牌,也可以预先加载所有数据,如果没有那么多数据,这可能是个好主意。