Лучшая практика для спасения всей коллекции?

Скажите, что у меня есть коллекция, и я внес изменения во многие из своих моделей. Каков наилучший способ сохранить все изменения с помощью одного HTTP-запроса?

Ответ 1

Обычно серверы REST обрабатывают создание/обновление отдельных экземпляров. Вам нужно будет изменить это, чтобы принять массив объектов.

Тем не менее, на стороне клиента вам нужно будет перейти непосредственно к функции Backbone.sync

Backbone.sync = function(method, model, options)

В этом случае ваша модель должна быть массивом модели. Метод должен быть "create" или "save", а опции имеют тот же тип параметров, что и jQuery ajax-вызов (ошибка, успех и т.д.).

Ответ 2

Я собираюсь сделать "Неправильную вещь" здесь и процитировать Википедию относительно правильных методов RESTful: a PUT example.com/resources должен заменить всю коллекцию другой коллекцией. Исходя из этого, когда нам приходилось поддерживать редактирование нескольких элементов одновременно, мы написали этот контракт.

  • Клиент отправляет {"resources": [{resource1},{resource2}]}
  • Сервер заменяет всю коллекцию новой информацией от клиента и возвращает информацию после ее сохранения: {"resources": [{"id":1,...},{"id":2,...}]}

Мы написали серверную часть контракта в Rails, но здесь клиентская половина (в CoffeeScript, извините!):

class ChildElementCollection extends Backbone.Collection
  initialize: ->
    @bind 'add', (model) -> model.set('parent_id', @parent.id)

  url: -> "#{@parent.url()}/resources" # let say that @parent.url() == '/parent/1'
  save: ->
    response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON()))
    response.done (models) => @reset models.resources

Я думал, что это намного проще реализовать, а затем переопределить Backbone.sync. Один комментарий к коду, наши коллекции всегда были дочерними объектами, которые должны объяснять, почему код устанавливает "parent_id" всякий раз, когда объект добавляется в коллекцию и как корень URL-адреса является родительским. Если у вас есть коллекции на уровне корня, которые вы хотите изменить, просто удалите бизнес @parent.

Ответ 3

Вы должны расширить Backbone.Collection, предоставив ему метод save(), который будет проверять каждую из его моделей hasChanged().

Затем он должен вызвать Backbone.sync, который вам, вероятно, придется немного расширить в пользовательскую функцию синхронизации. Если вы используете пользовательскую функцию Backbone.sync, то обязательно установите ее в своей коллекции.

var CollectionSync = function(method, model, [options]) {
    // do similar things to Backbone.sync
}

var MyCollection = Backbone.Collection.extend({
    sync: CollectionSync,
    model: MyModel,
    getChanged: function() {
        // return a list of models that have changed by checking hasChanged()
    },
    save: function(attributes, options) {
        // do similar things as Model.save
    }
});

Другой подход (с использованием модели для представления коллекции) находится здесь: "How" для сохранения целой коллекции в Backbone.js - Backbone.sync или jQuery.ajax?

Мне также нравится fooobar.com/questions/69792/...

Ответ 4

Этот код добавляет новый метод в прототип коллекции, чтобы вызвать метод сохранения тех моделей, которые были изменены. Это сработало для меня:

Backbone.Collection.prototype.saveAll = function(options) {
 return $.when.apply($, _.map(this.models, function(m) {
   return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
 }));
};

Ссылка Gist: https://gist.github.com/julianitor/701c677279bac1529b88