div - jquery this
¿La mejor práctica para guardar una colección completa? (4)
Debería ampliar Backbone.Collection
, dándole un método save()
que verificaría cada uno de sus modelos hasChanged()
.
Luego debe llamar a Backbone.sync
, que probablemente tendrá que extender un poco en una función de sincronización personalizada. Si usa una función Backbone.sync
personalizada, asegúrese de configurarla en su colección.
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
}
});
Un enfoque diferente (utilizando un modelo para representar la colección) está aquí: "Cómo" guardar una colección completa en Backbone.js - Backbone.sync o jQuery.ajax?
También me gusta https://stackoverflow.com/a/7986982/137067
Digamos que tengo una Colección y he realizado cambios en muchos de sus Modelos. ¿Cuál es la mejor manera de guardar todos los cambios con una sola solicitud HTTP?
Este código agrega un nuevo método al prototipo de recopilación solo para llamar al método guardar de los modelos que han cambiado. Funcionó para mí:
Backbone.Collection.prototype.saveAll = function(options) {
return $.when.apply($, _.map(this.models, function(m) {
return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
}));
};
Enlace de Gist: https://gist.github.com/julianitor/701c677279bac1529b88
Haré lo incorrecto aquí y citaré Wikipedia acerca de las prácticas RESTful correctas : un PUT a example.com/resources
debería reemplazar toda la colección con otra colección. En base a esto, cuando tuvimos que ayudar a editar varios ítems simultáneamente, redactamos este contrato.
- El cliente envía
{"resources": [{resource1},{resource2}]}
- El servidor reemplaza toda la colección con la nueva información del cliente y devuelve la información después de que se ha conservado:
{"resources": [{"id":1,...},{"id":2,...}]}
Escribimos la mitad del contrato del servidor en Rails, pero aquí está la mitad del cliente (en CoffeeScript, lo siento):
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
Pensé que esto era mucho más fácil de implementar que reemplazar Backbone.sync. Un comentario sobre el código, nuestras colecciones eran siempre objetos secundarios, lo que debería explicar por qué el código establece un "parent_id" cada vez que se agrega un objeto a la colección, y cómo la raíz de la URL es la URL principal. Si tiene colecciones de nivel raíz que desea modificar, simplemente elimine el negocio de @parent
.
Por lo general, los backends REST manejan la creación / actualización de instancias únicas. Debería cambiar eso para aceptar una matriz de objetos.
Dicho esto, en el lado del cliente, necesitaría ir directamente a la función Backbone.sync
Backbone.sync = function(method, model, options)
En este caso, su modelo debe ser una matriz de modelo. El método debe ser "crear" o "guardar" y las opciones toman el mismo tipo de opciones que una llamada jQuery ajax (error, éxito, etc.)