_.bindAll(this) и Uncaught TypeError: невозможно прочитать свойство idAttribute неопределенного в backbone-relation.js

У меня есть две модели (пользовательская и задача), которые являются экземплярами Backbone.RelationalModel.

Отношение к этим двум моделям следующее:

// Task model

    var Task = Backbone.RelationalModel.extend({

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

        urlRoot: 'someUrl'

    });

Затем у меня есть одна коллекция, код которой выглядит так:

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


var User = Backbone.RelationalModel.extend({

});

Когда я делаю выборку для FollowerCollection, я получаю следующую ошибку:

 Uncaught TypeError: Cannot read property 'idAttribute' of undefined

в строке 1565 backbone-relation.js из backbone-relation version 0.5.0


Вот кусок кода backbone-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 ] );

Проблема связана с _.bindAll(this), потому что если я его прокомментирую, он работает нормально.
Почему? Есть идеи?



person Lorraine Bernard    schedule 29.06.2012    source источник
comment
Вы уверены, что модель User определена при объявлении отношения?   -  person rinat.io    schedule 29.06.2012
comment
@mashingan Я приложил весь код о модели задачи. можешь дать посмотреть? Благодарю.   -  person Lorraine Bernard    schedule 29.06.2012
comment
Как насчет того, чтобы вы приложили код для FollowerCollection и User, чтобы мы могли хотя бы попытаться найти проблему? В настоящее время я не вижу никакой связи между этими двумя классами.   -  person jakee    schedule 29.06.2012
comment
@jakee, mashingan Я приложил код каждой модели и коллекции (основные части);   -  person Lorraine Bernard    schedule 29.06.2012
comment
следующий: код, где вы получаете указанную коллекцию   -  person jakee    schedule 29.06.2012
comment
@jakee, код FollowerCollection возвращает коллекцию пользователей, и все в порядке.   -  person Lorraine Bernard    schedule 29.06.2012
comment
@jakee, спасибо за помощь. проблема была в сборе. Я исправляю это, и я закрою этот вопрос через несколько минут.   -  person Lorraine Bernard    schedule 29.06.2012
comment
@jakee, что было не так в сборе, так это сделать _.bindAll(this). Можете ли вы объяснить мне, почему это тормозит код? Я изменил название своего вопроса.   -  person Lorraine Bernard    schedule 29.06.2012
comment
ну, _.bindAll(this) связывает this с каждой функцией в вашей коллекции, так что может случиться что угодно. Скорее всего, это приведет к тому, что this.model или this.model.prototype будут чем-то иным, чем того ожидает Backbone-relational. Нужен ли bindAll? Если это необходимо для какой-то функции в вашей коллекции, сделайте _.bindAll(this, 'funcname1', 'funcname2', ..., 'funcnameN'), чтобы выделить функции, к которым нужно привязать this.   -  person jakee    schedule 29.06.2012


Ответы (2)


Удаление _.bindAll работает.

А жаль, потому что это действительно удобная функция. Он должен плохо взаимодействовать с какой-то частью Backbone. я на версии 9.10

Я использую этот метод все время, и проблемы возникают только иногда (например, когда вы хотите сделать массовое добавление в коллекцию).

Для меня проблема была в этом методе 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];
},

Код терпит неудачу в this.model.prototype, потому что прототип не определен. Какой? Я. Для реалов.

Проблема в том, что когда вызывается _.bindAll, он связывает все свойства коллекции, как говорит @jakee. Кажется, это включает Collection.model, что, я думаю, является ошибкой.

Решение состоит в том, чтобы связать отдельные методы, пока это не будет исправлено.

На github есть существующая, но закрытая проблема: https://github.com/documentcloud/backbone/issues/2080 Кажется, нынешним сопровождающим этот метод не нравится, но я не понимаю, почему.

person SimplGy    schedule 20.02.2013

Поскольку мой проект действительно большой, мне пришлось создать свой собственный bindAll. Вот вам код, он работает с последними версиями. Я привязываю все свойства экземпляра «это», кроме тех, у которых есть прототип со свойствами, например this.model в коллекции.

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);

};

person ccsakuweb    schedule 18.12.2013