ember-data.js: https://github.com/emberjs/data/tree/0396411e39df96c8506de3182c81414c1d0eb981
つまり、エラーが発生した場合、ビューにエラーメッセージを表示し、ユーザーは1)キャンセルしてトランザクションをロールバックします2)入力エラーを修正してトランザクションを正常にコミットし、検証を渡します。サーバ。
以下はソースからのコードスニペットです。エラーコールバックは含まれていません。
updateRecord: function(store, type, record) {
var id = get(record, 'id');
var root = this.rootForType(type);
var data = {};
data[root] = this.toJSON(record);
this.ajax(this.buildURL(root, id), "PUT", {
data: data,
context: this,
success: function(json) {
this.didUpdateRecord(store, type, record, json);
}
});
},
全体として、サーバーからエラーを受け取り、ビューを更新するフローは何ですか?エラーコールバックによってモデルがisError
状態になり、ビューが適切なメッセージを表示できるようです。また、トランザクションはダーティのままである必要があります。このようにして、トランザクションはrollback
を使用できます。
store.recordWasInvalid
の使用は正しい方向に進んでいるようですが。
今週末、私は同じことを理解しようとしていました。ルークの発言を離れて、私は 最新のコミット (12月11日)のember-dataソースを詳しく調べました。
TLDR; ember-data update/createエラーを処理するには、DS.Model
インスタンスでbecameError()
およびbecameInvalid(errors)
を定義するだけです。 RESTadapterのAJAXエラーコールバックによってトリガーされるカスケードは、最終的には定義したこれらの関数を呼び出します。
例:
App.Post = DS.Model.extend
title: DS.attr "string"
body: DS.attr "string"
becameError: ->
# handle error case here
alert 'there was an error!'
becameInvalid: (errors) ->
# record was invalid
alert "Record was invalid because: #{errors}"
これがソースの完全なウォークです:
RESTアダプタでは、AJAXコールバックエラー関数が指定されています here :
this.ajax(this.buildURL(root, id), "PUT", {
data: data,
context: this,
success: function(json) {
Ember.run(this, function(){
this.didUpdateRecord(store, type, record, json);
});
},
error: function(xhr) {
this.didError(store, type, record, xhr);
}
});
didErrorが定義されています here そして、応答に応じて、次にストアのrecordWasInvalidまたはrecordWasErrorを呼び出します。
didError: function(store, type, record, xhr) {
if (xhr.status === 422) {
var data = JSON.parse(xhr.responseText);
store.recordWasInvalid(record, data['errors']);
} else {
store.recordWasError(record);
}
},
次に、store.recordWasInvalid
およびstore.recordWasError
(定義済み ここ )は、レコード(DS.Model)のハンドラーを呼び出します。無効な場合は、アダプターからのエラーメッセージを引数として渡します。
recordWasInvalid: function(record, errors) {
record.adapterDidInvalidate(errors);
},
recordWasError: function(record) {
record.adapterDidError();
},
DS.Model.adapterDidInvalidate
およびadapterDidError
(定義 ここ )は単にsend('becameInvalid', errors)
またはsend('becameError')
になり、最終的にハンドラーにつながります ここ :
didLoad: Ember.K,
didUpdate: Ember.K,
didCreate: Ember.K,
didDelete: Ember.K,
becameInvalid: Ember.K,
becameError: Ember.K,
(Ember.Kはthis
を返すためのダミー関数です。 ここ を参照)
したがって、結論は、これらのケースを処理するためにモデルでbecameInvalid
およびbecameError
の関数を定義する必要があるだけです。
これが他の誰かを助けることを願っています。ドキュメントは確かに現在これを反映していません。
DS.RESTAdapter
this commit でエラー処理が少し増えましたが、まだエラー処理についての推奨事項はありません。
(私が行ったように)ember-dataを使用してアプリを本番環境で運用する意欲的または夢中になっている場合は、APIで障害が発生する可能性が極めて低いことを確認することをお勧めします。つまり、クライアント側でデータを検証します。
うまくいけば、我々はこの質問を今後数ヶ月でより良い答えで更新することができます。
私はそのような状況に遭遇しました、これがすでにどこかで説明されているかどうかはわかりません。
使ってます:
Em.VERSION : 1.0.0
DS.VERSION : "1.0.0-beta.6"
Ember Validations (dockyard) : Version: 1.0.0.beta.1
Ember I18n
このモデルは、最初は検証ミックスインと混合されました。
App.Order = DS.Model.extend(Ember.Validations.Mixin, {
.....
someAttribute : DS.attr('string'),
/* Client side input validation with ember-validations */
validations : {
someAttribute : {
presence : {
message : Ember.I18n.t('translations.someAttributeInputError')
}
}
}
});
テンプレートには、対応するハンドルバーが追加されています。 (ember検証により、model.errors.<attribute>
入力検証の場合、サーバー検証でも同じトレードオフを使用します)
<p>{{t 'translations.myString'}}<br>
{{view Ember.TextField valueBinding="attributeName"}}
{{#if model.errors.attributeName.length}}<small class="error">{{model.errors.attributeName}}</small>{{/if}}
</p
ここで、Order
を保存します
App.get('order').save().then(function () {
//move to next state?
}, function(xhr){
var errors = xhr.responseJSON.errors;
for(var error in errors){ //this loop is for I18n
errors[error] = Ember.I18n.t(errors[error]);
}
controller.get('model').set('errors', errors); //this will overwrite current errors if any
});
サーバーからスローされた検証エラーがある場合、使用されている返されたパケットは
{"errors":{"attributeName1":"translations.attributeNameEror",
"another":"translations.anotherError"}}
status : 422
ステータスを使用することが重要です422
したがって、このようにして、属性をクライアント側で検証し、サーバー側で再度検証することができます。
免責事項:これが最善の方法かどうかはわかりません!
現在、Ember-Dataには適切なソリューションがないため、DS.ModelにapiErrors
プロパティを追加して独自のソリューションを作成し、次にRestAdapterサブクラスに(独自のソリューションが既に必要です)エラーコールバックをAjaxはcreateRecord
およびupdateRecord
を呼び出し、エラーを保存し、モデルを「無効な」状態にします。これは、クライアント側またはサーバー側の検証が失敗したことを意味します。
コードスニペットは次のとおりです。
これは、application.jsまたは他のいくつかの最上位ファイルに移動できます。
DS.Model.reopen({
// Added for better error handling on create/update
apiErrors: null
});
これは、RestAdapterサブクラスのcreateRecord
およびupdateRecord
のエラーコールバックに含まれます。
error: function(xhr, textStatus, err) {
console.log(xhr.responseText);
errors = null;
try {
errors = JSON.parse(xhr.responseText).errors;
} catch(e){} //ignore parse error
if(errors) {
record.set('apiErrors',errors);
}
record.send('becameInvalid');
}