我正在使用ember-data作为我的一个项目,我有一个问题围绕着污染对象的可能性,然后故意将其状态再次设置为清理 - 而不会提交更改。场景是这样的:
假设我通过banana = App.Fruit.find('banana');
获取了一个对象,并且它描述了“黄果!”。使用XHR长轮询(或WebSockets),我可能会收到对象的更新版本,因为另一个用户已将描述更改为“美味的黄色水果!”在任何给定的时间点之后我获取了原始对象。
然后,我想要做的是更新对象以反映新接收的数据。为此,我尝试了不同的方法:
我尝试过调用App.Store.load(App.Fruit, new_data);
。首先,这种方法不起作用,其次,这不是我想要的。我本可以对对象进行未提交的更改,在这种情况下,放弃那些(假设load()
调用会覆盖它们)是不可取的。
我尝试循环遍历新数据,调用.set()
- 如此:banana.set('description', new_data.description);
- 为了使用新数据更新对象属性(适用时=非脏) 。这样可以使对象处于脏污状态。
为了使对象再次清理/更新 - 不让适配器提交更改! - 我看了一下物体穿过的状态。这些是(至少):
rootState.loaded.saved
状态。.set()
会将其推送到rootState.loaded.updated.uncommitted
状态。App.store.commit();
将对象返回到rootState.loaded.saved
状态。因此,我尝试在步骤2之后手动将对象状态设置为saved
,如下所示:banana.get('stateManager').goToState('saved');
。
然而,这不起作用。下次商店因任何其他原因提交时,此操作会产生 inFlightDirtyReasons未定义错误。
我的问题是:我怎样才能手动将脏污物体的状态改回干净(保存)?
答案 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');
将脏记录设置为已加载并保存
答案 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.rollbackAttributes
:http://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
方法。