Подтвердить что ты не робот

Переопределить Backbone.sync() на уровне модели для отправки дополнительных параметров?

Честно говоря, я застрял, пытаясь переопределить метод Backbone sync() для модели, у меня есть подпись для функции на месте, и она запускается правильно, но Я не знаю, что поместите в тело функции, чтобы он сделал вызов по умолчанию DELETE, но с дополнительными аргументами. то есть.

class Master.Models.Member extends Backbone.Model
  urlRoot: '/api/members/'

  sync: (method, model, options) ->
    params = _.clone options
    Backbone.sync method, model, params

Я называю это следующим образом:

......
remove: ->
  @model.destroy
    collective_id: the_id

Мое намерение там - передать параметр collect_id, который вы видите там на сервере. Но даже несмотря на то, что внутри хэша опций для sync() и я его клонировал, он не попадет на сервер! Как я могу отправить этот дополнительный параметр на сервер?

(Как это, единственное, что достигает сервера - это идентификатор модели)

Спасибо заранее!

4b9b3361

Ответ 1

Когда вы вызываете .destroy(),.fetch() или .save(), все они вызывают Model.sync, который вызывает только Backbone.sync. Это прокси-функция. Это предназначено, чтобы обеспечить хороший крюк для изменения поведения AJAX одной модели или любых моделей, которые простираются от этой модели.

  • Решение 1: переопределите Global Backbone.sync на JSON.stringify и измените contentType, когда вы указали данные, которые должны быть отправлены с запросом удаления.
    • Плюсы: вы можете вызвать model.destroy() и опционально передать параметр options
  • Решение 2. Переопределите метод Model.sync.
    • Плюсы: переопределение влияет только на отдельные модели. Изолированные изменения.
    • Минусы: все модели, которые хотят удалить данные, должны быть расширены от правильной "базовой модели".
  • Решение 3. Не переопределяйте ничего и явно вызывайте model.sync со всеми вещами stringify и contentType.
    • Плюсы: очень изолированные изменения, не повлияют на какие-либо другие модели. Полезно, если вы интегрируетесь с большой базой кода.

[Решение 1] - Глобальное переопределение Backbone.sync(это повлияет на все модели)

версия javacript

var oldBackboneSync = Backbone.sync;
Backbone.sync = function( method, model, options ) {
    // delete request WITH data
    if ( method === 'delete' && options.data ) {
        options.data = JSON.stringify(options.data);
        options.contentType = 'application/json';
    } // else, business as usual.
    return oldBackboneSync.apply(this, [method, model, options]);
}

Использование

var model, SomeModel = Backbone.Model.extend({ /* urlRoot, initialize, etc... */});
model = new SomeModel();
model.destroy({
    data: {
        /* data payload to send with delete request */
    }
});

[Решение 2] - переопределить Backbone.destroy на базовой модели и расширить другие модели.

переопределить

// Create your own 'enhanced' model 
Backbone.EnhancedModel = Backbone.Model.extend({
    destroy: function( options ) {
        if ( options.data ) {
            // properly formats data for back-end to parse
            options.data = JSON.stringify(options.data);
        }
        // transform all delete requests to application/json
        options.contentType = 'application/json';
        Backbone.Model.prototype.destroy.call(this, options);
    }
});

Использование

var model, SomeModel = Backbone.EnhancedModel.extend({ /* urlRoot, initialize, etc... */})
model = new SomeModel();
SomeModel.destroy({
    data: {
        /* additional data payload */
    }
}); 

[Решение 3] - Вызовите .destroy() с правильными параметрами.

Если отправка данных с вашими запросами на уничтожение является изолированной, то это адекватное решение.

При вызове model.destroy() введите параметры data и contentType, например:

версия/использование javascript

var additionalData = { collective_id: 14 };
model.destroy({
    data: JSON.stringify(additionalData),
    contentType: 'application/json'
});

"Проблема" (с базой, а не с решениями):

Backbone.js делает предположение (просмотр источника), которое удаляет запросы не.

// delete methods are excluded from having their data processed and contentType altered.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
      params.contentType = 'application/json';
      params.data = JSON.stringify(options.attrs || model.toJSON(options));
}

В своем предполагаемом вызове API RESTful единственными требуемыми данными является идентификатор, который должен быть добавлен к свойству urlRoot.

var BookModel = Backbone.Model.extend({
    urlRoot: 'api/book'
});
var book1 = new BookModel({ id: 1 });
book1.destroy()

Запрос на удаление будет отправлен как

DELETE => api/book/1
contentType: Content-Type:application/x-www-form-urlencoded; charset=UTF-8

Ответ 2

Парамы необходимо отправить в options.data, поэтому попробуйте:

CoffeeScript

remove: () ->
  @model.destroy 
    data: JSON.stringify
      collective_id: the_id, 
    contentType: 'application/json'

Javascript

remove: function() {
  return this.model.destroy({
    data: JSON.stringify({
      collective_id: the_id
    }),
    contentType: 'application/json'
  });
}