Модель Backbone.js с коллекцией - PullRequest
37 голосов
/ 21 августа 2011

У меня 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 Ответ

56 голосов
/ 22 августа 2011

Ваша 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);
}

Вы также можете найти Магистрально-реляционный интересным - это значительно облегчает работу с коллекциями / моделями, вложенными в модели.

edit Я забыл вернуться из метода set (), код теперь обновляется

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...