24

解释:

我正在为我的一个项目使用 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状态。

因此,我尝试saved在第 2 步之后手动设置对象状态,如下所示banana.get('stateManager').goToState('saved');

但是,这不起作用。下次存储出于任何其他原因提交时,此操作会产生inFlightDirtyReasons is undefined错误。

问题:

我的问题是:如何手动将脏对象的状态再次更改为干净(已保存)?

4

13 回答 13

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 会让你手动更改状态。

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

于 2014-04-28T14:48:58.333 回答
12

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

这应该可以解决问题

record.get('stateManager').send('becameClean');  
于 2012-11-14T00:11:21.313 回答
10

Ember Data 2.6.1解决方案

record.send('pushedData');

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

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

于 2016-06-22T12:01:58.043 回答
7

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

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

record._internalModel.send('willCommit'); 
record._internalModel._attributes = {};
record._internalModel.send('didCommit');
于 2015-08-28T16:02:35.357 回答
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')
于 2013-07-08T16:15:23.863 回答
5

作为ember-data 1.0.0-beta.12:

record.transitionTo('loaded.saved');

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

于 2014-12-15T10:43:48.200 回答
4

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

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

不确定是否需要所有这些行,但只是遵循其他人在此之前所做的事情。

于 2014-10-15T11:59:59.347 回答
3

余烬 2.9.1

record.set('currentState.isDirty', false);
于 2017-05-12T22:48:25.140 回答
2

在 Ember Data 2.9 上测试

pushData 操作是可行的方法,但除此之外,还需要重置“originalValues”。

Ember.assign(record.data, record._internalModel._attributes);
Ember.assign(record._internalModel._data, record._internalModel._attributes);
record.send('pushedData');
于 2016-11-15T08:33:54.647 回答
1

看起来对于较新的版本,这里提到的所有内容都被破坏了。

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

record.adapterWillCommit();
record.adapterDidCommit();
于 2014-01-02T17:28:22.650 回答
1

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

record.rollback()

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

似乎这可能已经被弃用了record.rollbackAttributes: http: //emberjs.com/api/data/classes/DS.Model.html#method_rollbackAttributes

于 2015-08-21T20:15:06.187 回答
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()在此记录上进一步调用,如果我们将有一些脏属性,则记录将重置为最后一个状态(而不是具有原始属性),这正是我在使用中寻找的案子。

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

于 2018-05-15T17:46:56.293 回答
1

在 Ember Data 3.8.0 上测试

只是对 Martin Malinda 的 回答的更新:

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

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

在我的情况下,我还需要覆盖序列化程序的normalize方法。

于 2019-08-28T18:34:57.850 回答