1

ダーティ レコードを手動でクリーン状態に送信しようとしています( ember-data を使用してオブジェクトの状態を手動でクリーン (保存) に設定する方法に関連して)。

ember-data の望ましくない使用またはバグが原因で発生している可能性のある何かに出くわしました。

基本的に、私がやっていることは

  1. 問題のレコードを見つけ、
  2. .set()記録上の財産、および
  3. レコードを手動で「becameClean」状態に送信します。App.store.commit();これは、上記のリンク先の質問に記載されている理由で電話をかけたときに、レコードがコミットされるのを避けるために行われます。

始める前に、レコードがどの状態を通過するかを確認するために、ember-dataenter: function() { console.log(this); console.log(this.get('path')); }の部分に行を追加しました。DS.State = ...

私はGitHubの最新のプルオフを実行しています。これが私のアプローチです:

ステップ 1)電話App.Fruit.find('banana');:

  • console.log(this);結果:

    <DS.State:ember1077> { initialState="saved", isLoaded=true, saved=<DS.State:ember1078>, more...}

  • console.log(this.get('path'));結果:

    1. 「rootState.empty」
    2. 「rootState.loading」
    3. 「rootState.loaded」
    4. 「rootState.loaded.saved」

ステップ 2)電話App.Fruit.find('banana').set('description', 'Yellow fruit!');:

  • console.log(this);結果:

    <(subclass of DS.State):ember1084> { dirtyType="updated", childStates=[3], eventTransitions={...}, more...}

  • console.log(this.get('path'));結果:

    1. 「rootState.loaded.updated」

ステップ 3)電話App.store.get('defaultTransaction.buckets');:

  • 「更新された」バケットにレコードが表示されます

ステップ 4)電話App.Fruit.find('banana').get('stateManager').send('becameClean');:

  • console.log(this);結果:

    <DS.State:ember1078> { childStates=[0], eventTransitions={...}, states={...}, more...}

  • console.log(this.get('path'));結果:

    1. 「rootState.loaded.saved」

ステップ 5)電話App.store.get('defaultTransaction.buckets');:

  • 「クリーン」バケットにレコードが表示されます

インターミッション:オーケー、ここまではとても良かったです。レコードを正常な状態に送信できたようです。ただし、次のことが起こります。

ステップ 6)電話App.Fruit.find('banana').set('description', 'Even more yellow fruit!');:

  • console.log(this);結果:

    (なし)

  • console.log(this.get('path'));結果:

    (なし)

ステップ 7)電話App.store.get('defaultTransaction.buckets');:

  • 「クリーン」バケットにレコードが表示されます

問題は、'becameClean' 状態をレコードに送信した後、後でレコードを変更しても、'loaded.saved' 状態のままになることです。

ステップ 2 で新しいサブクラス オブジェクトがDS.Stateで作成されたdirtyType="updated"場合、ステップ 6 でもこれが発生しないのはなぜですか?

.send('becameClean')私の質問は次のとおりです。これはバグですか、それとも私の使用が望ましくないために機能しませんか?

4

1 に答える 1

1

短い答え

これは、レコードの状態マネージャーでイベントを手動でトリガーすることは、あなたが言うように「望ましくない」ためです。そうすることで、記録によって行われる他のすべての簿記を逃してしまいます。

これらの新しい値をサーバーから注入する唯一の安全な方法は、store.load(). (その理由を本当に知りたい場合は、下の詳細を参照してください。) これにより、適切な簿記が確実に行われます。

残念ながら、これは、コミットされていない変更が安全に隠蔽され、サイドローディング後に再適用されることを確認するのはあなた次第であることを意味します (サイドローディングはレコードのすべての属性を置き換えるため)。

長い答え

この場合、レコードを手動でクリーンとしてマークすると、内部的にいくつかのことが中断されます。(1)レコードのダーティ要素のリストはそのまま残り、(2)元の属性のレコードのコピーは変更されません。

(1)ダーティ ファクターとは、最後のコミット以降に変更されたプロパティ (属性と関連付け) です。レコードはこのリストを使用して、とりわけ、レコードをダーティ状態に移行する必要があるかどうかを判断します。説明などのプロパティを設定すると、ダーティ ファクタのリストがチェックされ、そのプロパティがすでに変更されているかどうかが確認されます。そうでない場合、およびレコードが現在「クリーン」と見なされている場合は、レコードをダーティ状態に移行します。

あなたの例では、説明を変更してから、レコードを手動でクリーンとしてマークしました。ただし、レコードはまだその説明がダーティであると考えていたため、2 回目に変更しようとしたときに、ダーティな状態に移行することは決してありませんでした。

(2)技術的には、ダーティな要素record.removeDirtyFactors()フラッシュしてレコードをクリーンな状態に移行するために使用できますが、そうしたとしても、元の属性のレコードのコピーは依然として間違っています。サーバーが実際には「B」であるときに「A」があったと見なします。その後、クライアントで「A」に戻してコミットしようとしても、レコードは何もしません。サーバーとの同期がすでに戻っていると見なされます。

于 2012-11-17T22:53:23.160 に答える