Модель Backbone.js с коллекцией
У меня есть 2 модели и одна коллекция. JobSummary
- это модель, JobSummaryList
- это набор элементов JobSummary
, а затем у меня есть модель JobSummarySnapshot
, содержащая JobSummaryList
:
JobSummary = Backbone.Model.extend({});
JobSummaryList = Backbone.Collection.extend({
model: JobSummary
});
JobSummarySnapshot = Backbone.Model.extend({
url: '/JobSummaryList',
defaults: {
pageNumber: 1,
summaryList: new JobSummaryList()
}
});
Когда я вызываю fetch
в объекте JobSummarySnapshot
, он получает все... Кроме того, когда я перемещаюсь по коллекции summaryList
, все они имеют тип object
, а не JobSummary
.
Я полагаю, что это имеет смысл, поскольку объект, отличный от объекта defaults
, не знает, что summaryList
должен иметь тип JobSummaryList
. Я могу пройти через каждый элемент и преобразовать его в объект JobSummary
, но я надеялся, что есть способ сделать это без необходимости делать это вручную.
Здесь мой тестовый код (рабочий jsfiddle здесь):
var returnData = {
pageNumber: 3,
summaryList: [
{
id: 5,
name: 'name1'},
{
id: 6,
name: 'name2'}
]
};
var fakeserver = sinon.fakeServer.create();
fakeserver.respondWith('GET', '/JobSummaryList', [200,
{
'Content-Type': 'application/json'},
JSON.stringify(returnData)]);
var callback = sinon.spy();
var summarySnapshot = new JobSummarySnapshot();
summarySnapshot.bind('change', callback);
summarySnapshot.fetch();
fakeserver.respond();
var theReturnedList = callback.getCall(0).args[0].attributes.summaryList;
_.each(theReturnedList, function(item) {
console.log('Original Item: ');
console.log(item instanceof JobSummary); // IS FALSE
var convertedItem = new JobSummary(item);
console.log('converted item: ');
console.log(convertedItem instanceof JobSummary); // IS TRUE
});
UPDATE:
Мне пришло в голову, что я могу переопределить функцию синтаксического анализа и установить ее таким образом... У меня есть это сейчас:
JobSummarySnapshot = Backbone.Model.extend({
url: '/JobSummaryList',
defaults: {
pageNumber: 1,
summaryList: new JobSummaryList()
},
parse: function(response) {
this.set({pageNumber: response.pageNumber});
var summaryList = new JobSummaryList();
summaryList.add(response.summaryList);
this.set({summaryList: summaryList});
}
});
Это работает до сих пор. Оставив вопрос открытым, если кто-то прокомментирует это....
Ответы
Ответ 1
Ваша функция parse()
не должна set()
что-либо, лучше всего вернуть атрибуты, Backbone позаботится о ее настройке. например.
parse: function(response) {
response.summaryList = new JobSummaryList(response.summaryList);
return response;
}
Что бы вы ни вернули из parse()
, передано set()
.
Не возвращать ничего (это похоже на возвращение undefined
) - это то же самое, что и вызов set(undefined)
, что может привести к тому, что он не пройдет проверку или другие неожиданные результаты, если ваши пользовательские методы validate()
/set()
для получения объекта. Если ваш метод проверки или set()
завершился с ошибкой из-за этого, обратный вызов options.success
, переданный в Backbone.Model#fetch()
, не будет вызываться.
Кроме того, чтобы сделать это более общим, так что set()
обращение к простому объекту из других мест (и не только от ответа сервера) также влияет на него, вы можете вместо этого заменить set()
:
set: function(attributes, options) {
if (attributes.summaryList !== undefined && !(attributes.summaryList instanceof JobSummaryList)) {
attributes.summaryList = new JobSummaryList(attributes.summaryList);
}
return Backbone.Model.prototype.set.call(this, attributes, options);
}
Вы также можете найти Backbone-relational интересное - это облегчает работу с коллекциями/моделями, вложенными внутри моделей.
edit Я забыл вернуться из метода set(), теперь код обновляется