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"}
очевидно, это json только для 1 задачи. Если вы посмотрите на проекты json, вы увидите, что я поместил массив «tasks» с идентификаторами в нем - вот как внутренняя часть знает, какие задачи получить. поэтому, чтобы ответить на ваш первый вопрос, вам не нужен идентификатор от потомка к родителю, вам нужно, чтобы родитель загружался со всеми потомками, поэтому 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
в источнике данных. Этот метод в свою очередь вызывает 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
, но вы можете предоставить свою собственную, если не хотите делать один запрос для каждой дочерней записи, которую вы загружаете.
Обратите внимание, что у вас всегда есть варианты. Если бы я захотел, я мог бы создать запрос «Задачи» и загрузить все данные о задачах заранее, так что мне не нужно было бы переходить на мой сервер, когда я щелкал проект. Так что в ответ на ваш второй вопрос, это зависит. Вы можете либо загружать бренды, когда нажимаете на клиента, либо загружать все данные заранее, что, вероятно, будет хорошей идеей, если данных не так много.