Ошибка: необходимо указать свойство или функцию URL-адреса, кроме указанного URL-адреса.

У меня есть модель разговора и представление, отображающее эту модель. Эта модель загружается с сервера без каких-либо проблем (в этом случае свойство url работает нормально), и представление отображается. Однако, когда я пытаюсь уничтожить модель в функции представления, я получаю сообщение об ошибке «Должно быть указано свойство или функция "url"», хотя когда я отображаю указанный URL-адрес прямо перед вызовом уничтожения, это именно тот URL должен быть.

Вот код модели:

MessageManager.models.Conversation = Backbone.Model.extend({
    defaults: {
        uid: '',
        title: '',
        messages: [],
        users: [],
        dateUpdated: null,
        isNew: true,
        message: ''
    },
    url: function(){
        var url = '/api/conversations';
        if(this.get('uid').length > 0) url += '/'+this.get('uid');
        return url;
    }
});

И вид:

MessageManager.views.ConversationFull = Marionette.CompositeView.extend({
    template: this.template(MessageManager.templates.ConversationFull),
    childView: MessageManager.views.MessageListItem,
    childViewContainer: '#message-container',
    events: {
        'click a#btn-delete-conversation': 'deleteConversation'
    },
    deleteConversation: function(e){
        e.preventDefault();
        var self = this;
        console.log(self.model.url()); //This returns a correct url

        self.model.destroy({//This fires the error
            error: function(model, result, xhr){
                console.log(result.responseText);
            },
            success: function(model, response, options){
                MessageManager.conversations.sync();
                AMMain.router.pNavigate('welcome/');
            }
        });
    }
});

Может ли кто-нибудь дать некоторое представление о том, как решить эту проблему? Что-то не так в том, как я объявляю модель?

РЕДАКТИРОВАТЬ: следует отметить, что другие вызовы (например, выборка или синхронизация) в этой модели вызывают ту же ошибку, хотя исходная выборка работает без проблем.

EDIT2: Ну, еще не совсем из сковороды, но я изменил способ определения URL-адреса модели, используя urlRoot и атрибут «id», и теперь запрос DELETE отправляется на сервер без ошибок.


person Gabriel Theron    schedule 16.10.2014    source источник


Ответы (2)


defsq ответ хороший. Единственное, чего не хватает, — это определить idAttribute в вашей модели, поскольку это не основанное на соглашении поле id, а uid.

MessageManager.models.Conversation = Backbone.Model.extend({
    idAttribute: 'uid',
    defaults: {
        uid: '',
        title: '',
        messages: [],
        users: [],
        dateUpdated: null,
        isNew: true,
        message: ''
    },
    urlRoot: "/api/conversations"
});

Вам не нужно добавлять «id» вручную. Просто скажите Backbone, что ваш атрибут id равен uid, и все остальное будет работать. Фактически, вы можете вызвать событие mymodel.id, чтобы получить идентификатор модели -event, если он хранится внутри как uid. :)

http://backbonejs.org/#Model-idAttribute

Лично мне не нравятся все эти значения по умолчанию. Все будет undefined, если вы не установите значения по умолчанию, от которых вы можете просто защититься с помощью if (undefined - это значение falsey).

if(!model.get("messages")){
   //no messages
}
person CharlieBrown    schedule 16.10.2014
comment
Я искал, как использовался idAttribute! Большое спасибо! - person Gabriel Theron; 16.10.2014
comment
Затем отметьте как отвеченный, чтобы будущие пользователи узнали. рад помочь! ;) - person CharlieBrown; 16.10.2014

Это происходит потому, что вы должны указать urlRoot свойство модели. Без него url не считается. Итак, попробуйте это, возможно:

MessageManager.models.Conversation = Backbone.Model.extend({
    defaults: {
        uid: '',
        title: '',
        messages: [],
        users: [],
        dateUpdated: null,
        isNew: true,
        message: ''
    },
    urlRoot: function() {
        var url = '/api/conversations';
        if (this.get('uid').length > 0) url += '/'+this.get('uid');
        return url;
    }
});

Документация говорит:

urlRootmodel.urlRoot или model.urlRoot() Укажите urlRoot, если вы используете модель вне коллекции, чтобы включить функцию URL по умолчанию для создания URL-адресов на основе идентификатора модели. "[urlRoot]/id" Обычно вам не нужно определять это. Обратите внимание, что urlRoot также может быть функцией.

И исходный код для метода Backbone.Model url:

url: function() {
  var base =
    _.result(this, 'urlRoot') ||
    _.result(this.collection, 'url') ||
    urlError();
  if (this.isNew()) return base;
  return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
},
person dfsq    schedule 16.10.2014
comment
Я добавил атрибут urlRoot, и у меня больше нет ошибки. Однако вместо вызова метода DELETE на сервере функция уничтожения переходит непосредственно к успеху с неопределенным ответом. Кажется, что-то все еще идет не так внутри, как я могу выяснить, что? Кроме того, успешный вызов не выполняет остальные вызовы (например, синхронизацию и навигацию), что крайне странно, учитывая, что вызов console.log все еще может произойти. Как будто после этого звонка совсем онемел позвоночник. - person Gabriel Theron; 16.10.2014