web-dev-qa-db-ja.com

ember-dataを使用してオブジェクトの状態を手動でクリーンアップ(保存)に設定する方法

説明:

私は自分のプロジェクトにember-dataを使用していますが、オブジェクトをダーティし、変更をコミットせずに意図的にその状態を再びクリーンに設定する可能性を中心に質問があります。シナリオは次のとおりです。

banana = App.Fruit.find('banana');を介してオブジェクトをフェッチし、「黄色い果物!」という説明があるとします。 XHRロングポーリング(またはWebSocket)を使用すると、別のユーザーが説明を「おいしい黄色い果物!」に変更したために、オブジェクトの更新バージョンを受け取る場合があります。任意の時点afterで元のオブジェクトをフェッチしました。

次に、新しく受信したデータを反映するようにオブジェクトを更新します。このために、私はさまざまなアプローチを試しました。

  • App.Store.load(App.Fruit, new_data);を呼び出してみました。まず第一に、このアプローチは機能しません、そして第二に、これは本当に私が望むものではありません。自分でオブジェクトにコミットされていない変更を加えることもできますが、この場合、それらを単に破棄することは望ましくありません(load()呼び出しがそれらを上書きすると仮定します)。

  • オブジェクトのプロパティを新しいデータで更新するために、.set()-のように:banana.set('description', new_data.description);-を呼び出して、新しいデータをループしようとしました(該当する場合=ダーティではありません)。これは機能しますが、オブジェクトは汚れた状態のままになります。

オブジェクトを再度クリーン/更新するために-およびnotアダプタに変更をコミットさせます! -オブジェクトが通過する状態を確認しました。これらは(少なくとも):

  • ステップ1:最初、オブジェクトは_rootState.loaded.saved_状態です。
  • 手順2:プロパティで.set()を呼び出すと、プロパティが_rootState.loaded.updated.uncommitted_状態になります。
  • ステップ3:App.store.commit();を呼び出すと、オブジェクトは_rootState.loaded.saved_状態に戻ります。

したがって、次のように、手順2の後でオブジェクトの状態を手動でsavedに設定しようとしました:banana.get('stateManager').goToState('saved');

ただし、これは機能しません。次回ストアが他の理由でコミットすると、この操作によりinFlightDirtyReasons is undefinedエラーが生成されます。

質問:

私の質問は、汚れたオブジェクトの状態を手動で元に戻してクリーン(保存)に戻すにはどうすればよいですか?

23
Kasper Tidemann

Ember-dataを見ると、コミットされていない状態には「becameClean」イベントがあり、その結果、レコードがloaded.savedとして設定されます。

これはトリックを行う必要があります

record.get('stateManager').send('becameClean');  
11
Loadx

Ember Data 1.0.0-beta.7の解決策:

// changing to loaded.updated.inFlight, which has "didCommit" 
record.send('willCommit'); 
// clear array of changed (dirty) model attributes
record.set('_attributes', {});
// changing to loaded.saved (hooks didCommit event in "inFlight" state)
record.send('didCommit');

Ember-dataのソースコードを検索したところ、loaded.saved状態には、「保存済み」状態を設定する前に、モデルがクリーンかどうかをチェックするセットアップ機能があることがわかりました。クリーンでない場合は、状態を変更する要求を拒否し、loaded.updated.uncommittedに戻ります。

したがって、クリーンにする必要がありますmodel._attributes配列は、属性名を保持し、Emberを使用すると、状態を手動で変更できます。

モデルのプライベートプロパティを設定する必要があるため、あまり良い解決策ではないことはわかっていますが、他の解決策はまだ見つかりません。

24
Kamil J.

Ember Data 2.6.1のソリューション

record.send('pushedData');

ダーティレコードをロードおよび保存済みとして設定

https://github.com/emberjs/data/blob/fec260a38c3f7227ffe17a3af09973ce2718acca/addon/-private/system/model/states.js#L25

10
elatonsev

これは@ Kamil-jのソリューションのアップデートです。

現在使用しているEmber Data 2.0の場合、次の手順を実行する必要があります。

record._internalModel.send('willCommit'); 
record._internalModel._attributes = {};
record._internalModel.send('didCommit');
6
Serge

_ember-data_ _1.0.0-beta.12:_現在

_record.transitionTo('loaded.saved');
_

record.get('stateManager')はもう必要ないようです。

5
Aymerick

1.0.0.rc6.2以降...

これにより、モデルが保存されたモデルの状態に移行します。

record.get('stateManager').transitionTo('loaded.saved') 

これにより、モデルがコミットされていない新しいモデルの状態に移行します。新しい汚れたモデルを考えてください。

record.get('stateManager').transitionTo('loaded.created.uncommitted')

これにより、モデルが更新された古いモデルの状態に移動します。古いダーティモデルを考えてみてください。

record.get('stateManager').transitionTo('loaded.updated')
5
Intentss

エンバー2.9.1

record.set('currentState.isDirty', false);
3
brayancastrop

Ember Data 1.0.0-beta.10:で機能すると思われるものは次のとおりです。

record.set('currentState.stateName', 'root.loaded.saved');
record.adapterWillCommit();
record.adapterDidCommit();
record.set('currentState.isDirty', false);

これらすべての行が必要かどうかはわかりませんが、これより前に他の人が行ったことに従うだけです。

3
Antti Hukkanen

テスト済みEmberデータ2.9

pushDataアクションは進むべき道ですが、それに加えて「originalValues」もリセットする必要があります。

Ember.assign(record.data, record._internalModel._attributes);
Ember.assign(record._internalModel._data, record._internalModel._attributes);
record.send('pushedData');
1
Martin Malinda

Ember Data 1.0.0-beta.18:を使用するときに私のために働いた別の方法

record.rollback()

これにより、ダーティ属性が逆になり、レコードがクリーンな状態に戻りました。

record.rollbackAttributesを支持して、このように廃止された可能性があります: http://emberjs.com/api/data/classes/DS.Model.html#method_rollbackAttributes

1
Jeff E

私はエンバーデータ1.1に取り組んでいるので、次のソリューションを使用しました(@Martin Malindaによって提供されたものと@Sergeによって提供されたものの混合のようです):

_// Ensure you have the changes inside the record
Object.assign(record.data, record._internalModel._attributes);
Object.assign(record._internalModel._data,record._internalModel._attributes);

// Using the DS.State you can first simulate the record is going to be saved
record.get('_internalModel').send('willCommit');

// Cleaning the prevous dirty attributes
record.get('_internalModel')._attributes = {};

// Mark the record as saved (root.loaded.created.uncommitted) even if it isn't for real
record.get('_internalModel').send('didCommit');
_

このように、このレコードでさらにrollbackAttributes()を呼び出すと、ダーティな属性がある場合、レコードは(元のプロパティではなく)この最後の状態にリセットされます。私は自分のユースケースで探していました。

ダーティ属性がない場合、何も変更されず、このコードを使用して設定された最後の属性を、元の属性にロールバックせずに保持します。それが役に立てば幸い。

1
AndreaScn

新しいバージョンでは、ここで説明したすべてが壊れたようです。

これはember-data 1.0.0.beta4:でうまくいきました

record.adapterWillCommit();
record.adapterDidCommit();
1
Andriy Buday

テスト済みEmberデータ3.8.0

マーティンマリンダの 回答 の更新:

// Clear changed attributes list 
record._internalModel._recordData._attributes = {};

// Trigger transition to 'loaded.saved' state
record.send('pushedData');

私の場合、シリアライザーのnormalizeメソッドもオーバーライドする必要がありました。

0