2012-06-29 22 views
6

Tengo dos modelos (usuario y tarea) que son instancias de Backbone.RelationalModel._.bindTodos (esto) y TypeError no detectado: no se puede leer la propiedad 'idAttribute' de undefined en backbone-relation.js

La relación de estos dos modelos es el siguiente:

// Task model 

    var Task = Backbone.RelationalModel.extend({ 

     relations: [ 
      { 
       type: 'HasOne', 
       key: 'user', 
       relatedModel: User 
      } 
     ], 

     urlRoot: 'someUrl' 

    }); 

Entonces tengo una colección que código es el siguiente:

var FollowerCollection = Backbone.Collection.extend({ 
    initialize: function() { 
     _.bindAll(this); 
    } 
    model: User 
}); 


var User = Backbone.RelationalModel.extend({ 

}); 

cuando hago una zona de alcance de FollowerCollection I recibe el siguiente error:

Uncaught TypeError: Cannot read property 'idAttribute' of undefined 

en la línea 1565 de la cadena principal-relation.js de backbone-relation version 0.5.0


Aquí una pieza de código de cadena principal relation.js

if (!(model instanceof Backbone.Model)) { 
    // Try to find 'model' in Backbone.store. If it already exists, set the new properties on it. 
     var existingModel = Backbone.Relational.store.find(this.model, model[ this.model.prototype.idAttribute ]); 

El problema está relacionado con _.bindAll(this) porque si Lo comento, funciona correctamente.
¿Por qué? ¿Algunas ideas?


+0

¿Está seguro de que el modelo 'Usuario' se define cuando declara la relación? –

+0

@mashingan Adjunté todo el código sobre el modelo de Tarea. ¿Puedes echarle un vistazo? Gracias. –

+0

¿Qué tal si adjuntamos el código de FollowerCollection y User para que podamos intentar encontrar el problema? Actualmente no veo relación alguna entre las dos clases. – jakee

Respuesta

3

Quitar _.bindAll funciona.

Es una pena, porque es una función realmente práctica. Debe interactuar mal con alguna parte de Backbone. Estoy en v9.10

Utilizo este método todo el tiempo, y los problemas solo surgen a veces (como cuando quiere hacer un agregado masivo a una colección).

Para mí, el problema estaba en este método Backbone.js:

// Get a model from the set by id. 
get: function(obj) { 
    if (obj == null) return void 0; 
    this._idAttr || (this._idAttr = this.model.prototype.idAttribute); 
    return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj]; 
}, 

El código de falla en this.model.prototype porque prototipo no está definido. ¿Qué? Ya. Deveras.

El problema es que cuando se llama a _.bindAll, enlaza todas las propiedades de la colección, como dice @jakee. Esto parece incluir Collection.model, que es un error, creo.

La solución es enlazar métodos individuales hasta que esto se solucione.

Existe un problema existente, pero cerrado en github: https://github.com/documentcloud/backbone/issues/2080 Parece que a los mantenedores actuales no les gusta el método, pero no entiendo por qué.

0

Al igual que mi proyecto es realmente grande, tuve que crear mi bindAll personalizado. Aquí tienes el código, funciona con las últimas versiones. Ato todas las propiedades de la instancia "this" excepto las que tienen un prototipo con propiedades, como esta.modelo en una colección

https://gist.github.com/patrixd/8025952

//bindAll from underscore that allows 1 argument to bind all the functions from the prototype, 
//or if there are more arguments they will be the only binded 
_.originalBindAll = _.bindAll; 
_.bindAll = function (that) { 
     var funcs = Array.prototype.slice.call(arguments, 1), 
      validKeys = [], fn; 
     if (funcs.length == 0) { 
     for (var i in that) { 
      fn = that[i]; 
      if (fn && typeof fn == "function" && (!fn.prototype ||   
       _.keys(fn.prototype).length == 0)) 
       validKeys.push(i); 
    } 
    _.originalBindAll.apply(_, [that].concat(validKeys)); 
} 
else 
    _.originalBindAll.apply(_, arguments); 

};

Cuestiones relacionadas