Ember.js 如何回滚数据中的关系更改
我有两种亲子关系模式:培训和锻炼:Ember.js 如何回滚数据中的关系更改,ember.js,ember-data,relationships,Ember.js,Ember Data,Relationships,我有两种亲子关系模式:培训和锻炼: App.Training=DS.Model.extend({ 练习:DS.hasMany('App.Exercise') }) App.Exercise=DS.Model.extend({ 培训:DS.belongsTo('App.training') }) 我想有一个页面,其中显示培训及其所有相关练习。如果用户按下Edit按钮,页面将变为可编辑,并可能添加新练习。我还想要一个取消按钮,该按钮将放弃所做的所有更改 这是我的控制器: App.trainings
App.Training=DS.Model.extend({
练习:DS.hasMany('App.Exercise')
})
App.Exercise=DS.Model.extend({
培训:DS.belongsTo('App.training')
})
我想有一个页面,其中显示培训及其所有相关练习。如果用户按下Edit
按钮,页面将变为可编辑,并可能添加新练习。我还想要一个取消
按钮,该按钮将放弃所做的所有更改
这是我的控制器:
App.trainingshowcontroller=Em.ObjectController.extend({
编辑:错,
编辑:函数(){
此.set('editing',true);
transaction=this.get('store').transaction();
transaction.add(this.get('model'));
this.get('model.exercises').forEach(函数(x){
交易记录。添加(x);
});
},
取消:函数(){
此.set('editing',false);
this.get('model.transaction').rollback();
},
保存:函数(){
此.set('editing',false);
this.get('model.transaction').commit();
},
addExercise:function(){
this.get('model.exercises').createRecord({});
}
})
控制器中有四个事件处理程序:
edit
:用户按下edit
按钮:创建事务,页面进入“编辑”模式取消
:用户按下了取消
按钮:事务回滚并返回到“正常”模式save
:用户按下save
按钮:事务提交并返回“正常”模式addExercise
:用户按下了addExercise
按钮:将创建一个新的练习(在同一事务中)并将其添加到培训中编辑
按钮,添加新练习并按下取消
按钮,新创建的练习将保留在页面上
什么是摆脱被丢弃的儿童记录的最佳方法
更新:
我创建了一个JSFIDLE来重现这个问题,但它成功了。与这里的应用程序不同,我使用了DS.FixtureAdapter
:
然后我使用DS.RESTAdapter
创建了另一个,问题出现了:
在小提琴中尝试:编辑,添加新的,然后回滚
我发现,在RESTAdapter的情况下,当我向hasMany
关系添加新的子记录时,父记录不会变脏。这似乎很好,但当我回滚事务时,新创建的子记录将保留在父级的ManyArray
中
我仍然不知道,处理这种情况的最佳方法是什么。这不太好,但您可以通过手动弄脏父记录来强制它回滚:
parent.send('becomeDirty');
parent.rollback();
parent.get('children.length'); // => 0
@托塔达和其他读者跟随。从
Ember Data:1.0.0-beta.10+canary.7db210f29a开始
当回滚子级时,父级仍然不能使parentTraining.isDirty()
的值为true。当一个属性被更改时,Enbe数据会考虑一个父记录,但是当<代码> DS时,Engult>不< /强> .HasMule数组有更改(工作,因此您可以更新服务器上的父属性的任何更改)。
对于上面提到的情况,要对新创建的子记录执行
rollback()
,解决方法是将要丢弃的子记录上的.rollback()
替换为.deleteRecord()
。然后,余烬数据自动知道将其从DS中删除。然后,有许多
数组,您可以拍拍自己的后背,以获得出色的回滚效果 余烬数据中严重缺乏对hasMany和belongsTo关系进行适当的脏检查和回滚。它当前的行为方式通常被报告为bug。这对于许多开发人员来说是一个巨大的痛点,这里正在讨论如何解决这个问题:
在找到合适的解决方案之前,您可以使用以下方法解决此问题
首先,您需要重新打开DS.Model并对其进行扩展。如果您使用的是globals,您可以将它(例如DS.Model.reopen({}))放在任何地方,但是如果您使用的是Ember CLI,最好创建一个初始值设定项(例如Ember g初始值设定项Model):
上面的代码本质上存储了加载或更新时的原始关系,以便以后可以用于回滚和脏检查
model.rollback()现在应该回滚所有内容,包括hasMany和belongsTo关系。不过,我们还没有完全解决“isDirty”检查问题。为此,我们需要在模型的具体实现中覆盖isDirty。我们之所以需要在这里执行此操作,而不能在DS.Model中一般地执行此操作,是因为DS.Model不知道要监视哪些属性更改。下面是一个使用Ember CLI的示例。globals也会使用相同的方法,只是您会将此类分配给类似App.Book的对象:
import DS from 'ember-data';
var Book = DS.Model.extend({
publisher: DS.belongsTo('publisher'),
authors: DS.hasMany('author'),
isDirty: function() {
return this.isDeepDirty();
}.property('currentState', 'publisher', 'authors.[]', 'authors.@each.isDirty').readOnly()
});
export default Book;
对于isDirty的依赖参数,请确保包括所有belongsTo关系,并为每个hasMany关系包括'array.[]'和'array.@each.isDirty'。现在isDirty应该如预期的那样工作了。晚会迟到了,但现在我们开始: 我创建了一个插件来解决这个问题。 只需调用
rollbackrelations()
,它将回滚您的所有关系(belongsTo&hasMany)。有关更多选项,请参阅自述文件
这是一个好主意,但现在我的应用程序似乎正在立即加载所有异步关系(这需要一段时间),而不是等到实际使用异步关系?如果我错了,请纠正我。@justastefan,观察得好。saveOriginalRelations可能正在加载所有异步关系。如果你有
import DS from 'ember-data';
var Book = DS.Model.extend({
publisher: DS.belongsTo('publisher'),
authors: DS.hasMany('author'),
isDirty: function() {
return this.isDeepDirty();
}.property('currentState', 'publisher', 'authors.[]', 'authors.@each.isDirty').readOnly()
});
export default Book;