Автоматическое создание подклассов и переклассификация списка объектов CanJS

Удаленный сторонний сервер JSONP предоставляет моему скрипту CanJS список результатов, подобный этому:

[
    { "class": "ABaseClass", "value": "1"},
    { "class": "ASubClass", "value": "2"},
    { "class": "ABaseClass", "value": "3"},
    { "class": "ASubClass", "value": "4"}, 
    ...
]

где type — предполагаемый класс объекта, определенный в CanJS с использованием can.Model.extend:

Следующий упрощенный код демонстрирует настройку CanJS:

ABaseClass = can.Model.extend({ ... }, {
    'findAll': { 'url': 'the url', 'dataType': "jsonp" }
    // this is modified source code and may not run
});

// ASubClass is a subclass of ABaseClass.
ASubClass = ABaseClass.extend({ ... }, { ... });

Проблема:

Когда вызывается ABaseClass.findAll({}, function(data) { ... }), который вызывает конечные точки JSONP для большего количества объектов, обратный вызов получает список моделей CanJS, но только класса ABaseClass.

Вопрос:

Есть ли в CanJS вспомогательный метод для автоматического создания подклассов на основе поля в списке объектов? Если нет, как я могу его реализовать?


Ожидаемый результат:

[
    (new ABaseClass(...)),
    (new ASubClass(...)),
    (new ABaseClass(...)),
    (new ASubClass(...)),
    ...
]

Окружающая среда:

  • CanJS: 1.17
  • jQuery: 1.10.1
  • Я не могу контролировать, какие типы объектов возвращает конечная точка.
  • Множественные вызовы AJAX не являются приемлемым решением.

person Brian    schedule 16.08.2013    source источник
comment
Я могу попробовать, вы ожидаете, что результатом findAll будет массив ABaseClass.List, can.List или js?   -  person complistic    schedule 03.02.2014
comment
@complistic С тех пор я перешел на Backbone (см. дату), но любое из имеющихся у вас рабочих решений для этого вопроса определенно поможет сообществу CanJS.   -  person Brian    schedule 03.02.2014


Ответы (1)


Самый простой способ сделать это — переопределить метод models и найти правильную модель для класса следующим образом:

ABaseClass = can.Model.extend('ABaseClass', {
    'findAll': { url: "/the_url", dataType: "jsonp" },
    models: function(results){
        return_models = new can.List();
        can.each(results, function(result){
            return_models.push( window[result.class].model(result.value) )
        })
        return return_models;
    }
}, {});

ASubClass = ABaseClass.extend('ASubClass', {}, {});

ABaseClass.findAll({}, function(results){
    console.log(results);
})

Что это делает:

  1. Когда findAll возвращается, он отправляет результат методу models.
  2. Затем метод models перебирает каждый из результатов.
  3. Затем он находит конструктор модели, прикрепленный к окну. ( window[result.class] )
  4. Затем мы вызываем model в конструкторе для создания/обновления экземпляра модели.
  5. Добавьте экземпляр модели в can.List и верните его.

Я протестировал это в CanJS 2.0.x, и здесь все работает нормально.

Вы можете найти более подробную информацию о том, как все это работает, в документации:

Похоже, что они будут объявлены устаревшими в CanJS 2.1.0 в пользу .parseModels и .parseModel.

person complistic    schedule 04.03.2014