2013-03-20 21 views
9

Mam kolekcję zwierząt.Kolekcja szkieletu polimorficznych modeli

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

i te zajęcia zwierząt:

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'} 

Gdy kolekcja jest wypełniona JSON (zapisy zawierają atrybut typu) Chcę modele do wystąpienia jako modele sub-klasyfikowane (małpa, kot, Dog), a nie jako Animal. Jak możesz to osiągnąć?

Odpowiedz

12

Od Backbone documentation:

Zbiór może zawierać także modele polimorficzne nadrzędnymi tej nieruchomość na funkcję zwracającą modelu.

var Library = Backbone.Collection.extend({ 

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

}); 
0

Zastąp element _prepareModel kolekcji kręgosłupa. Kolekcja new używa podklas, gdy jest zdefiniowana inaczej, używa modelu domyślnego.

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

Rozwiązanie jest proste (przeproszeniem JS, nie wiem 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); 
     } 
    } 
}); 

Musisz:

  1. Dołącz atrybut w modelu z który można określić rodzaj modelu szkieletu do utworzenia. W tym przykładzie moje obiekty zawierają atrybut o nazwie "typ", którego wartością jest pełna nazwa typu szkieletu, który go reprezentuje. Należy go ustawić w wartościach domyślnych lub zainicjować model, aby można było dodać do kolekcji również rzeczywiste instancje modelu.
  2. Definiowanie właściwości modeli swojej kolekcji jako funkcji. Pierwszym parametrem tej funkcji będzie surowy obiekt JS (jeśli to właśnie przekazałeś) lub obiekt atrybutu modelu szkieletu. Tak czy inaczej, możesz uzyskać dostęp do pola typu jako własności tego obiektu.
  3. Wykonaj swoją logikę, aby wywnioskować właściwy model z pola typu.
  4. Zwraca wystąpienie odpowiedniego modelu z funkcji modeli.

Oto JSFiddle że pokazuje to polimorficzny kolekcję w akcji: http://jsfiddle.net/FiddlerOnTheTarmac/uR2Sa/

+0

Wystarczy pamiętać, że jeśli zbiór może mieć wiele modeli 'if(); jeśli jeszcze; else' jest znacznie bardziej wydajne niż 'switch' – seebiscuit