Скажите, что у меня есть коллекция, и я внес изменения во многие из своих моделей. Каков наилучший способ сохранить все изменения с помощью одного 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