Dites que j'ai une collection et que j'ai apporté des modifications à plusieurs de ses modèles. Quel est le meilleur moyen de sauvegarder toutes les modifications en utilisant une seule requête HTTP?
Généralement, les serveurs REST gèrent la création/mise à jour d'instances uniques. Vous devrez changer cela pour accepter un tableau d'objets.
Cela dit, côté client, vous devrez passer directement à la fonction Backbone.sync
Backbone.sync = function(method, model, options)
Dans ce cas, votre modèle devrait être un tableau de modèles. La méthode doit être "créer" ou "enregistrer" et les options prennent le même type d'options qu'un appel ajax jQuery (erreur, succès, etc.)
Je vais faire la mauvaise chose ici et citer Wikipedia concernant les bonnes pratiques RESTful : aPUTto example.com/resources
devrait remplacer la collection entière par une autre collection. Sur cette base, lorsque nous avons dû prendre en charge l'édition simultanée de plusieurs éléments, nous avons rédigé ce contrat.
{"resources": [{resource1},{resource2}]}
{"resources": [{"id":1,...},{"id":2,...}]}
Nous avons écrit la moitié du contrat du serveur dans Rails, mais voici la moitié du client (en CoffeeScript, désolé!):
class ChildElementCollection extends Backbone.Collection
initialize: ->
@bind 'add', (model) -> model.set('parent_id', @parent.id)
url: -> "#{@parent.url()}/resources" # let's 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
Je pensais que c’était un lot plus facile à mettre en œuvre que de remplacer Backbone.sync. Un commentaire sur le code, nos collections étaient toujours des objets enfants, ce qui devrait expliquer pourquoi le code définit un "parent_id" lorsqu'un objet est ajouté à la collection et comment la racine de l'URL est l'URL du parent. Si vous souhaitez modifier des collections au niveau de la racine, supprimez simplement l'activité @parent
.
Vous devriez étendre Backbone.Collection
, en lui donnant une méthode save()
permettant de vérifier chacun de ses modèles hasChanged()
.
Ensuite, il devrait appeler Backbone.sync
, que vous devrez probablement étendre un peu dans une fonction de synchronisation personnalisée. Si vous utilisez une fonction Backbone.sync
personnalisée, veillez à la définir dans votre collection.
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
}
});
Une approche différente (en utilisant un modèle pour représenter la collection) est la suivante: "Comment" enregistrer une collection entière dans Backbone.js - Backbone.sync ou jQuery.ajax?
J'aime aussi https://stackoverflow.com/a/7986982/137067
Ce code ajoute une nouvelle méthode au prototype de collection simplement pour appeler la méthode de sauvegarde des modèles modifiés. Cela a fonctionné pour moi:
Backbone.Collection.prototype.saveAll = function(options) {
return $.when.apply($, _.map(this.models, function(m) {
return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
}));
};
Lien Gist: https://Gist.github.com/julianitor/701c677279bac1529b88