web-dev-qa-db-fra.com

La meilleure pratique pour sauvegarder une collection entière?

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?

33
a paid nerd

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.)

24
Julien

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.

  1. Le client envoie {"resources": [{resource1},{resource2}]}
  2. Le serveur remplace l'intégralité de la collection par les nouvelles informations du client et les renvoie après leur persistance: {"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.

12
carpeliam

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

6
philfreo

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

0
juliantoledo