コレクションがあり、そのモデルの多くに変更を加えたとします。単一の HTTP 要求を使用してすべての変更を保存する最良の方法は何ですか?
4 に答える
通常、REST バックエンドは単一インスタンスの作成/更新を処理します。オブジェクトの配列を受け入れるように変更する必要があります。
つまり、クライアント側では、Backbone.sync 関数に直接移動する必要があります。
Backbone.sync = function(method, model, options)
この場合、モデルはモデルの配列でなければなりません。メソッドは「作成」または「保存」である必要があり、オプションは jQuery ajax 呼び出しと同じタイプのオプション (エラー、成功など) を取ります。
私はここで間違ったことをし、適切な RESTful プラクティスに関してウィキペディアを引用します: PUT toexample.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'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
これは、 Backbone.sync をオーバーライドするよりもはるかに簡単に実装できると思いました。コードに関する 1 つのコメントとして、私たちのコレクションは常に子オブジェクトであり、オブジェクトがコレクションに追加されるたびにコードが「parent_id」を設定する理由と、URL のルートが親の URL である理由を説明する必要があります。変更したいルートレベルのコレクションがある場合は、@parent
ビジネスを削除するだけです。
拡張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
}
});
別のアプローチ (モデルを使用してコレクションを表す) は次のとおりです: Backbone.js でコレクション全体を保存する「方法」 - Backbone.sync または jQuery.ajax?
このコードは、変更されたモデルの保存メソッドを呼び出すためだけに、コレクション プロトタイプに新しいメソッドを追加します。それは私のために働いた:
Backbone.Collection.prototype.saveAll = function(options) {
return $.when.apply($, _.map(this.models, function(m) {
return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
}));
};
要点リンク: https://gist.github.com/julianitor/701c677279bac1529b88