如何使用ember-data手动设置对象状态以清理(保存)

时间:2012-11-12 10:41:16

标签: ember.js ember-data

说明:

我正在使用ember-data作为我的一个项目,我有一个问题围绕着污染对象的可能性,然后故意将其状态再次设置为清理 - 而不会提交更改。场景是这样的:

假设我通过banana = App.Fruit.find('banana');获取了一个对象,并且它描述了“黄果!”。使用XHR长轮询(或WebSockets),我可能会收到对象的更新版本,因为另一个用户已将描述更改为“美味的黄色水果!”在任何给定的时间点之后我获取了原始对象。

然后,我想要做的是更新对象以反映新接收的数据。为此,我尝试了不同的方法:

  • 我尝试过调用App.Store.load(App.Fruit, new_data);。首先,这种方法不起作用,其次,这不是我想要的。我本可以对对象进行未提交的更改,在这种情况下,放弃那些(假设load()调用会覆盖它们)是不可取的。

  • 我尝试循环遍历新数据,调用.set() - 如此:banana.set('description', new_data.description); - 为了使用新数据更新对象属性(适用时=非脏) 。这样可以使对象处于脏污状态。

为了使对象再次清理/更新 - 让适配器提交更改! - 我看了一下物体穿过的状态。这些是(至少):

  • 步骤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未定义错误。

问题:

我的问题是:我怎样才能手动将脏污物体的状态改回干净(保存)?

13 个答案:

答案 0 :(得分:24)

解决 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则允许你手动更改状态。

我知道这不是一个很好的解决方案,因为需要设置模型的私有属性,但我还没有找到任何其他解决方案。

答案 1 :(得分:10)

查看ember-data,未提交的状态有一个'becomeClean'事件,因此将记录设置为loaded.saved。

这应该可以解决问题

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

答案 2 :(得分:9)

Ember Data 2.6.1

的解决方案
record.send('pushedData');

将脏记录设置为已加载并保存

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

答案 3 :(得分:6)

这是对@ Kamil-j解决方案的更新。

对于我目前正在使用的Ember Data 2.0,我必须执行以下操作:

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

答案 4 :(得分:5)

自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 :(得分:5)

截至ember-data 1.0.0-beta.12:

record.transitionTo('loaded.saved');

似乎不再需要 record.get('stateManager')

答案 6 :(得分:3)

这里似乎适用于Ember Data 1.0.0-beta.10:

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

不确定是否所有这些行都是必需的,但只是遵循其他人之前的行。

答案 7 :(得分:3)

Ember 2.9.1

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

答案 8 :(得分:1)

看起来新版本的所有内容都被打破了。

这对我有用 ember-data 1.0.0.beta4:

record.adapterWillCommit();
record.adapterDidCommit();

答案 9 :(得分:1)

使用Ember Data 1.0.0-beta.18时,另一种方法对我有用:

record.rollback()

这颠倒了脏属性并将记录返回到干净状态。

似乎这样做可能已被弃用,转而使用record.rollbackAttributeshttp://emberjs.com/api/data/classes/DS.Model.html#method_rollbackAttributes

答案 10 :(得分:1)

我使用 Ember数据1.13 ,因此我使用了以下解决方案(这似乎是@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(),如果我们将有一些脏属性,记录将被重置为最后一个状态(而不是具有原始属性)我在用例中寻找的是什么。

如果我们没有任何脏属性,那么什么都不会改变,我们将保留使用此代码设置的最后一个属性,而不会将它们回滚到原始属性。希望它有所帮助。

答案 11 :(得分:0)

在Ember Data 2.9上测试

pushData动作是要走的路,但除了那个" originalValues"也需要重置。

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

答案 12 :(得分:0)

在Ember Data 3.8.0上进行了测试

只需更新马丁·马林达(Martin Malinda)的answer

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

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

就我而言,我还需要重写序列化程序的normalize方法。