2013-03-20 4 views
9

У меня есть коллекция животных.Магистральная коллекция полиморфных моделей

App.Collections.Animals extends Backbone.Collection 
    model: App.Animal 
    url: '/animals/' #returns json 

И эти животные классы:

App.Models.Animal extends Backbone.Model 

App.Models.Monkey extends App.Models.Animal 
    defaults:{type:'Monkey'} 

App.Models.Cat extends App.Models.Animal 
    defaults:{type:'Cat'} 

App.Models.Dog extends App.Models.Animal 
    defaults:{type:'Dog'} 

Когда коллекция заполняется JSON (записи содержат типа атрибут) Я хочу модели, чтобы быть создан в качестве суб-классифицироваться моделей (обезьяны, кошки, Собака), а не как Животное. Как вы можете достичь этого?

ответ

12

От Backbone documentation:

Коллекция может также содержать полиморфные модели путем переопределения этого свойства с функцией, которая возвращает модель.

var Library = Backbone.Collection.extend({ 

    model: function(attrs, options) { 
    if (condition) { 
     return new PublicDocument(attrs, options); 
    } else { 
     return new PrivateDocument(attrs, options); 
    } 
    } 

}); 
0

Переоценка коллекции _prepareModel. Новая коллекция использует подклассы, если в противном случае используется модель по умолчанию.

class App.Collections.Animals extends Backbone.Collection 

model: App.Models.Animal 

_prepareModel: (attrs, options) -> 
    if attrs instanceof Backbone.Model 
    attrs.collection = @ 
    return attrs 

    options || (options = {}) 
    options.collection = @ 
    model_class = APP.Models[attrs.ntype] or this.model 
    model = new model_class(attrs, options) 
    if (!model._validate(attrs, options)) 
    false 
    else 
    model 
6

Решение просто (простите за JS, я не знаю, CoffeeScript):

var SmartZoo = Backbone.Collection.extend({ 
    model: function (attrs, options) { 
     // This code assumes that the object looks something like '{ type: "Cat", ... }'. 
     switch (attrs.type) { 
      case 'Cat': 
       return new Cat(attrs, options); 
      case 'Dog': 
       return new Dog(attrs, options); 
      default: // Unknown subclass 
       return new Animal(attrs, options); 
     } 
    } 
}); 

Вы должны:

  1. Включите атрибут в модели от который вы можете вывести тип модели Backbone для создания. В этом примере мои объекты содержат атрибут под названием «type», значение которого является полным именем типа Backbone, который его представляет. Обязательно установите его в настройках по умолчанию или инициализации вашей модели, чтобы вы могли также добавить реальные экземпляры модели в коллекцию.
  2. Определите свойство моделей вашей коллекции как функции. Первым параметром этой функции будет исходный объект JS (если это то, что вы передали), или объект атрибутов модели Backbone. В любом случае вы можете получить доступ к своему типу в качестве свойства этого объекта.
  3. Выполнение вашей логики для вывода правильной модели из поля вашего типа.
  4. Возврат экземпляра правильной модели из функции моделей.

Вот JSFiddle, который показывает эти полиморфные коллекции в действии: http://jsfiddle.net/FiddlerOnTheTarmac/uR2Sa/

+0

Сразу отметит, что если коллекция может иметь множество моделей 'если(); else if; else' намного более эффективен, чем 'switch' – seebiscuit

Смежные вопросы