2013-03-20 14 views
9

Ich habe eine Sammlung von Tieren.Backbone Sammlung von polymorphen Modellen

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

Und diese Tierklassen:

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

Wenn Sammlung mit JSON gefüllt (Datensätze enthalten die Typ Attribut) Ich möchte Modelle als Unter eingestuft Modelle (Affe, Katze auszuprägen, Hund) und nicht als Tier. Wie können Sie das erreichen?

Antwort

12

Von Backbone documentation:

Eine Sammlung kann durch Überschreiben dieser Eigenschaft mit einer Funktion polymorphe Modelle enthalten auch die ein Modell zurückgibt.

var Library = Backbone.Collection.extend({ 

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

}); 
0

Überschreiben Sie das _prepareModel der Backbone-Sammlung. Die Sammlung new verwendet Unterklassen, wenn sie anders definiert ist, verwendet das Standardmodell.

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

Die Lösung ist sehr einfach (das JS verzeihen, ich weiß nicht, 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); 
     } 
    } 
}); 

Sie müssen:

  1. ein Attribut in Ihrem Modell Fügen Sie aus Sie können den Typ des zu erstellenden Backbone-Modells ableiten. In diesem Beispiel enthalten meine Objekte ein Attribut namens "type", dessen Wert der vollständige Name des Backbone-Typs ist, der es darstellt. Stellen Sie sicher, dass Sie es in den Standardeinstellungen festlegen oder initialisieren, damit Sie der Auflistung auch reale Modellinstanzen hinzufügen können.
  2. Definieren Sie die Modelleigenschaft Ihrer Sammlung als Funktion. Der erste Parameter für diese Funktion ist das Raw-JS-Objekt (wenn Sie das übergeben haben) oder das Attributobjekt eines Backbone-Modells. In beiden Fällen können Sie auf Ihr Typfeld als eine Eigenschaft dieses Objekts zugreifen.
  3. Führen Sie Ihre Logik aus, um das richtige Modell aus Ihrem Typfeld abzuleiten.
  4. Geben Sie eine Instanz des korrekten Modells aus der Modellfunktion zurück.

Hier ist eine JSFiddle, die diese polymorphen Sammlung in Aktion zeigt: http://jsfiddle.net/FiddlerOnTheTarmac/uR2Sa/

+0

Es genügt zu bemerken, dass, wenn die Sammlung viele Modelle kann 'if(); sonst wenn; else' ist viel leistungsfähiger als 'switch' – seebiscuit

Verwandte Themen