Melhor prática para salvar uma coleção inteira?
-
14-11-2019 - |
Pergunta
Digamos que eu tenha uma coleção e fiz alterações em muitos de seus modelos.Qual é a melhor maneira de salvar todas as alterações usando uma única solicitação HTTP?
Solução
Normalmente, os back-ends REST lidam com a criação/atualização de instância única.Você precisaria mudar isso para aceitar uma matriz de objetos.
Dito isto, do lado do cliente, você precisaria ir diretamente para a função Backbone.sync
Backbone.sync = function(method, model, options)
Neste caso, seu modelo deve ser uma matriz de modelo.O método deve ser "criar" ou "salvar" e as opções assumem o mesmo tipo de opções que uma chamada jQuery ajax (erro, sucesso, etc.)
Outras dicas
Vou fazer a coisa errada aqui e citar a Wikipedia sobre práticas RESTful adequadas:a COLOCAR para example.com/resources
deve substituir toda a coleção por outra coleção.Com base nisso, quando tivemos que suportar a edição de vários itens simultaneamente, redigimos este contrato.
- O cliente envia
{"resources": [{resource1},{resource2}]}
- O servidor substitui toda a coleção pelas novas informações do cliente e retorna as informações após persistirem:
{"resources": [{"id":1,...},{"id":2,...}]}
Escrevemos a metade do contrato do servidor em Rails, mas aqui está a metade do cliente (em CoffeeScript, desculpe!):
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
Eu pensei que isso era um muito mais fácil de implementar do que substituir Backbone.sync.Um comentário sobre o código: nossas coleções sempre foram objetos filhos, o que deve explicar por que o código define um "parent_id" sempre que um objeto é adicionado à coleção e como a raiz da URL é a URL do pai.Se você tiver coleções de nível raiz que deseja modificar, basta remover o @parent
negócios.
Você deveria estender Backbone.Collection
, dando-lhe um save()
método que verificaria cada um de seus modelos hasChanged()
.
Então deveria ligar Backbone.sync
, que você provavelmente terá que estender um pouco para uma função de sincronização personalizada.Se você usar um personalizado Backbone.sync
função e certifique-se de configurá-la em sua coleção.
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
}
});
Uma abordagem diferente (usando um modelo para representar a coleção) está aqui: “Como” salvar uma coleção inteira em Backbone.js – Backbone.sync ou jQuery.ajax?
eu também gosto https://stackoverflow.com/a/7986982/137067
Este código adiciona um novo método ao protótipo da coleção apenas para chamar o método save dos modelos que foram alterados.Funcionou para mim:
Backbone.Collection.prototype.saveAll = function(options) {
return $.when.apply($, _.map(this.models, function(m) {
return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
}));
};
Link principal: https://gist.github.com/julianitor/701c677279bac1529b88