同期するときにモデルから特定のプロパティを除外する方法はありますか?
たとえば、ビューステートに関するモデル情報を保持しています。ピッカーモジュールがあり、このモジュールがモデルのselected
属性を切り替えるだけだとします。後で、コレクションで.save()
を呼び出すとき、selected
の値を無視して、サーバーへの同期から除外したいと思います。
そうするきれいな方法はありますか?
(詳細が必要な場合はお知らせください)
これは最良の解決策のようです(@nikoshr参照の質問に基づく)
Backbone.Model.extend({
// Overwrite save function
save: function(attrs, options) {
options || (options = {});
attrs || (attrs = _.clone(this.attributes));
// Filter the data to send to the server
delete attrs.selected;
delete attrs.dontSync;
options.data = JSON.stringify(attrs);
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
}
});
そのため、モデルインスタンスの保存関数を上書きしますが、不要なデータをフィルターで除外し、それを親プロトタイプ関数にプロキシします。
Underscore 1.3.3では pick が追加され、1.4.0では omit が追加されました。これは、モデルのtoJSON
関数をホワイトリスト属性にオーバーライドするために非常に簡単に使用できます_.pick
を使用するか、_.omit
を使用するブラックリスト属性を使用します。
また、toJSON
はデータをサーバーに渡すためにsyncコマンドで使用されるため、toJSON
を使用する他の場所でこれらのフィールドが必要ない限り、これは良いソリューションだと思います。
Backbone.Model.extend({
blacklist: ['selected',],
toJSON: function(options) {
return _.omit(this.attributes, this.blacklist);
},
});
私のソリューションは上記のすべてを組み合わせています。ブラックリストの代わりにホワイトリストを使用してください..これは一般的に良いルールです
定義する
attrWhiteList:['id','biography','status'],
そして、保存を上書きします
save: function(attrs, options) {
options || (options = {});
//here is whitelist or all
if (this.attrWhiteList != null )
// Filter the data to send to the server
whitelisted = _.pick(this.attributes, this.attrWhiteList);
else
whitelisted =this.attributes;
/* it seems that if you override save you lose some headers and the ajax call changes*/
// get data
options.data = JSON.stringify(whitelisted);
if ((this.get('id') == 0) || (this.get('id') == null))
options.type = "POST"
else
options.type = "PUT";
options.contentType = "application/json";
// options.headers = {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json'
// },
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
},
実際、この動作が永続的であるとは思わないため、バックボーンの保存または同期機能を台無しにせずにこれを達成するはるかに簡単な方法があります
backbone.jsの1145行目を見ると、
// Ensure that we have the appropriate request data.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
params.contentType = 'application/json';
params.data = JSON.stringify(options.attrs || model.toJSON(options));
}
つまり、オプションにデータを入力することにより、xhrのデータ部分をオーバーライドできます。
バックボーンの保存にはmodel.save([attributes]、[options])が必要なため
ただし、適切な保存にはidなどの属性が不可欠であることを忘れないでください
例
model.save( {}, { data: JSON.stringify(data) } ) ;
だから、あなたはこのようなことをするべきです
var data = { id : model.id , otherAttributes : 'value' } ;
model.save( {}, { data : JSON.stringify(data) } );
これは私にとって非常にうまく機能し、フェッチ、保存、削除などのxhrを備えたバックボーンで使用できます...
Options.dataがBackboneの呼び出し方法を変更するため、受け入れられたソリューションにいくつかの問題が見つかりました。以下のようにoptions.attrsを使用することをお勧めします。
Backbone.Model.extend({
save: function (attrs, options) {
options = options || {};
attrs = _.extend({}, _.clone(this.attributes), attrs);
// Filter the data to send to the server
delete attrs.selected;
options.attrs = attrs;
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
}
});
いくつかの答えに基づいて、これは、contentType
if options.data
はすでに設定されています:
EDITABLE_ATTRIBUTES = ["name", "birthdate", "favoriteFood"];
...
save: function(attrs, options) {
// `options` is an optional argument but is always needed here
options || (options = {});
var allAttrs = _.extend({}, this.attributes, attrs);
var allowedAttrs = _.pick(allAttrs, EDITABLE_ATTRIBUTES);
// If `options.data` is set, Backbone does not attempt to infer the content
// type and leaves it null. Set it explicitly as `application/json`.
options.contentType = "application/json";
options.data = JSON.stringify(allowedAttrs);
return Backbone.Model.prototype.save.call(
this, allowedAttrs, options);
},
Set options.attrsを使用すると、APIパラメーターをカスタマイズできます。
var model = new Backbone.Model();
model.save(null, {
wait: true,
success: function() {
},
attrs: _.omit(model.attributes, 'selected')
});
save
はtoJSON
を使用するため、オーバーライドします。
toJSON: function(options) {
var attr = _.clone(this.attributes);
delete attr.selected;
return attr;
},
ただし、toJSONを使用しており、たとえばビューでselected
が必要な場合は機能しない場合があります。それ以外の場合は、おそらくsave
メソッドをオーバーライドする必要があります。
必要な値のみを設定するには、HTTP POSTの代わりにHTTP PATCHを使用します。バックボーン側で、saveメソッドにパッチ属性を追加するだけです:
entity.save(data,{patch:true})
この属性でsaveを使用すると、data
として渡されたフィールドのみがサーバーに送信されます。
1回限りの場合は、mode.unset('selected', { silent:true })
(変更イベントの発生を避けるためだけにサイレントが設定されます)を使用して、属性を削除できます。ただし、保存後に再設定します。
これは、上記の解決策の1つを完全に推奨することです。さらに、これがより定期的に必要なものである場合。
この同じ問題を抱えて、私は助けることができる小さなモジュールを作成することにしました: https://github.com/lupugabriel1/backbone-model-save
これはあなたのモデルでそれを使用する方法です:
var myModel = new Backbone.ModelSave.extend({
notSync: ['name', 'age']
});