2011-05-19 13 views
6

Tengo una colección BackboneJS llamada History que puede contener uno de varios modelos Backbone JS (que se extienden desde HistoryItem que se extiende desde Backbone.Model), tratando de encontrar una manera de tener esto recreado cuando cargando, lamentablemente parece que la colección BackboneJS solo puede especificar en un modelo particular, por ejemploColección Backbone.Js con tipos específicos

HistoryCollection = Backbone.Model.extend({ 
    model: app.models.HistoryItem 
}) 

Lo que realmente tiene que hacer es determinar esto según el tipo, esto es lo que me gustaría hacer

HistoryCollection = Backbone.Model.extend({ 
    model: function(item) { 
     return app.models[item.type]; } }) 

Todas las ideas antes de Backbone tenedor para implementar esto? (es decir, un atributo de modelo de colección que puede tomar una función)

Respuesta

7

Jugando en firebug ... se le ocurrió un enfoque donde puede anular el método de análisis en lugar de especificar el modelo. Su puesta en práctica de análisis, básicamente, se convierte en una fábrica sencillo para llenar la colección con modelos que desea:

var BaseModel = Backbone.Model.extend({ 
    meth: function(){ return 'Base method'; }, 
}); 

var SubModel = BaseModel.extend({ 
    meth: function(){ return 'Sub1 method'; } 
}); 

var SubModel2 = BaseModel.extend({ 
    meth: function(){ return 'Sub2 method'; } 
}); 

var ModelCollection = Backbone.Collection.extend({ 
    parse: function(data){ 
     var self = this; 
     data.forEach(function(item){ 
      switch(item.type){ 
      case 1: 
       self.add(new SubModel(data)); 
       break; 
      case 2: 
       self.add(new SubModel2(data)); 
       break; 
      default: 
       self.add(new BaseModel(data)) 
     } 
}); 
    } 
}); 

//Example Use 
x = new ModelCollection; 
x.parse([{type: 1},{type: 2}, {type: 99}]); 
x.map(function(e){ return e.meth();}); 
+0

Gracias por esto. Me ayudó a resolver un problema que tenía en otra pregunta (http://stackoverflow.com/questions/7140741/backbone-js-model-with-collection). Nunca se me ocurrió usar la función de análisis ... –

0

yo sólo he implementado esta característica y comenzó con el consejo de Jake Dempsey, sin embargo en realidad se necesita reemplazar un método diferente en la colección. Este es el código que utilicé:

var MyCollection = Backbone.Collection.extend({ 

    _prepareModel: function(model, options) { 
     if (!(model instanceof Backbone.Model)) { 
      var attrs = model; 

      switch (attrs.type) { 
       case 1 : 
        model = new ModelType1(attrs, { collection: this }); 
        break; 

       case 2 : 
        model = new ModelType2(attrs, { collection: this }); 
        break; 

       default : 
        model = new BaseModel(attrs, { collection: this }); 
        break; 
      } 

      if (model.validate && !model._performValidation(attrs, options)) model = false; 
     } else if (!model.collection) { 
      model.collection = this; 
     } 

     return model; 
    } 

}); 

Tenga en cuenta que se trata de un método privado (más o menos) por lo que es algo a tener en cuenta cuando se actualiza la espina dorsal.

4

en mi humilde opinión, prefiero jugar con el método de modelo de la colección:

var MyCollection = Backbone.Collection.extend({ 
    model : function(attrs, options){ 
    switch (attrs.type) { 
      case 1 : 
       model = new ModelType1(attrs, options); 
       break; 

      case 2 : 
       model = new ModelType2(attrs, options); 
       break; 

      default : 
       model = new BaseModel(attrs, options); 
       break; 
    } 
    } 
}); 

o utilizando un modelo de poder:

ProxyModel = Backbone.Model.extend({ 
initialize: function() { 
    switch (this.get('type')) { 
    case 1 : 
     model = new ModelType1(attrs, options); 
     break; 

    case 2 : 
     model = new ModelType2(attrs, options); 
     break; 

    default : 
     model = new BaseModel(attrs, options); 
     break; 
    } 
    return new model; 
} 
}) 


var MyCollection = Backbone.Collection.extend({ 
    model : ProxyModel, 
}); 
Cuestiones relacionadas