Подтвердить что ты не робот

Модель 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});
    }
});

Это работает до сих пор. Оставив вопрос открытым, если кто-то прокомментирует это....

4b9b3361

Ответ 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(), теперь код обновляется