调用myModel.save()返回过时的模型 [英] Calling myModel.save() Returning Outdated Model

查看:196
本文介绍了调用myModel.save()返回过时的模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在更新后保存Ember Data DS.Model ,但是当我调用 myModel.save(),我发现Ember Data正在发送原始的,未更新的模型,而不是更新的模型。我想了解为什么会发生这种情况,我需要做的不同。



这里有一些细节。首先,我有两个模型:



/models/OrgUser.js:

  DS.Model.extend({
...
orgPerson:DS.belongsTo('org-person',{inverse:'org-user',async :true,embedded:'always'}),
});

请注意,我使用自定义的 RESTSerializer (见下文),所以唯一使用嵌入的:'always'是我的自定义 RESTSerializer 处理它的方式。 / p>

/models/OrgPerson.js:

  DS.Model.extend({
...
orgUser:DS.belongsTo('org-user'),
})

要保留这些模型,我使用的是 RESTAdapter 。为了生成包含上述两个模型的我的API的单个JSON请求,我已经对适配器进行了单一的自定义。我不认为这是什么影响,但是为了防止我错过了一些事情,这里是:



/serializers/application.js: / strong>

  DS.RESTSerializer.extend({
serializeBelongsTo:function(record,json,relationship){
var key = relationship.key;
key = this.keyForRelationship?this.keyForRelationship(key,'belongsTo'):key;

var data = record.get('data ');

if(relationship.options.embedded&& relationship.options.embedded ==='always'){
json [key] = data [relationship.key] ?data [relationship.key] .get('data'):null;
}
else {
json [key] = data [relationship.key]?data [relationship.key] .get('id'):null;
}

if(relationships.options.polymorphic){
this.serializePolymorphicType(record,json,relationship);
}
}
})

使用该设置,我有一个更新orgPerson属性的模板。我可以确认这些是绑定的属性,因为更新他们的输入实时更新他们的显示在模板的另一部分。然后我在控制器上调用一个动作,并在该操作中执行以下操作:



/ controllers /my-page.js:

 导出默认Ember.ObjectController.extend(FormMixin,{
操作:{
submitForm:function(){
...
this.get('model')// Chrome控制台显示_data.orgPerson._data.firstName具有(不正确)旧的属性
this.get('model')。serialize()//返回(不正确)old firstName
this.get('orgPerson.firstName')//返回(正确)更新firstName
this.get('orgPerson')。get('firstName')//返回(正确)更新firstName
...
}
}
});

任何想法为什么我得到两个不同版本的同一机型?如何序列化正确更新的模型?感谢任何输入!



解决方案:



感谢(再次!)到@ kingpin2k,解决了这个问题。以下是我采取的步骤:




  • 我的串行器实际上是问题,并使用Ember的旧保留数据。我将行 data [relationship.key] .get('data')替换为行 data [relationship.key] .serialize(),这是固定的。

  • 然后遇到另一个问题,那就是如果我编辑我的记录,没有保存,然后回到我的列表的记录,列表仍然显示编辑。我的第一个想法是,我需要更新我的列表页面的数组模型来仅显示最新的内容,但似乎没有任何Ember的设施。 li>
  • 所以我最终通过在我的路由中使用以下代码来解决这个问题。请注意,因为 orgPerson async:true 我不得不将我的模型包裹在一个承诺中。还要注意,我不得不直接调用 model.orgPerson 而不是仅仅模型



更新的路线:

  actions:{
willTransition:function(transition){
this.controller.get('model.orgPerson')。then(function(value){
if (value.get('isDirty')){
value.rollback();
}
});
}
}




  • 只需要调用 this.controller.get('model')。rollback(),所以我要编写一个通过 eachRelationship ,然后在任何对象上单独调用 rollback()。呃,很多细微的,让这个工作正常。


解决方案

数据 obj中的值。它将修改后的值存储在 _attributes obj中。在保存期间,将$ code> _attributes obj移动到FlightAttributes obj中的中,然后在保存完成后,将它们从 inFlightAttributes 数据。所有这一切都是您可以回滚您的记录。



当您将属性定义为 attr 时,它会将魔术获取起始位置 _attributes ,然后 inFlightAttributes ,然后 data 并返回该属性的结果。 >

  function getValue(record,key){
if(record._attributes.hasOwnProperty(key)){
return record._attributes [键]。
} else if(record._inFlightAttributes.hasOwnProperty(key)){
return record._inFlightAttributes [key];
} else {
return record._data [key];
}
}

https://github.com/emberjs/ data / blob / v1.0.0-beta.8 / packages / ember-data / lib / system / model / attributes.js#L267



在你的情况下,Ember Data不知道您正在保存该记录,并且您正在从数据 obj手动抓取旧属性。您需要手动将 _attributes 合并到数据,或者将Ember Data视为保存它。 / p>

I am attempting to save an Ember Data DS.Model after it's been updated, but when I call myModel.save(), I'm finding that Ember Data is sending the original, non-updated model instead of the updated one. I'm trying to understand why this is happening and what I need to do differently.

Here are some details. First, I have two models:

/models/OrgUser.js:

DS.Model.extend({
    ...
    orgPerson: DS.belongsTo('org-person', { inverse: 'org-user', async: true, embedded: 'always' }),
});

Note that I am using a customized RESTSerializer (see below), so the only use of embedded: 'always' is how my custom RESTSerializer handles it.

/models/OrgPerson.js:

DS.Model.extend({
   ...
   orgUser: DS.belongsTo('org-user'),
})

To persist these models, I'm using the RESTAdapter. In an attempt to generate a single JSON request to my API that contains both models above, I've made a single customization to the adapter. I don't think this is affecting anything, but just in case I'm missing something, here it is:

/serializers/application.js:

DS.RESTSerializer.extend({
    serializeBelongsTo: function(record, json, relationship) {
        var key = relationship.key;
        key = this.keyForRelationship ? this.keyForRelationship(key, 'belongsTo') : key;

        var data = record.get('data');

        if (relationship.options.embedded && relationship.options.embedded === 'always') {
            json[key] = data[relationship.key] ? data[relationship.key].get('data') : null;
        }
        else {
            json[key] = data[relationship.key] ? data[relationship.key].get('id') : null;
        }

        if (relationship.options.polymorphic) {
          this.serializePolymorphicType(record, json, relationship);
        }
    }
})

With that setup, I have a template where I update the orgPerson properties. I can confirm these are bound properties because updating their input updates their display on another part of the template in real-time. I then call an action on my controller, and within that action do the following:

/controllers/my-page.js:

export default Ember.ObjectController.extend( FormMixin, {
   actions: {
        submitForm: function() {
            ...
            this.get('model') // Chrome console shows that _data.orgPerson._data.firstName has the (incorrect) old property
            this.get('model').serialize() // returns (incorrect) old firstName
            this.get('orgPerson.firstName') // returns (correct) updated firstName
            this.get('orgPerson').get('firstName') // returns (correct) updated firstName
         ...
        }
    }
});

Any idea why I am getting two different versions of the same model? How can I serialize the correctly updated model? Thanks for any input!

SOLUTION:

Thanks (again!) to @kingpin2k, I have resolved this issue. Here are the steps I took:

  • My serializer was in fact the problem, and using Ember's old preserved data. I replaced the line data[relationship.key].get('data') with the line data[relationship.key].serialize() and this was fixed.
  • I then ran into another issue, which was that if I edited my record, did NOT save it, and then went back to my list of records, the list still showed the edit. My first thought was that I needed to update my list page's array model to show only the latest content, but there didn't appear to be any Ember facilities for this.
  • So I ultimately solved this by using the following code in my route. Note that because orgPerson is async: true I had to wrap my model in a promise. Note also that I had to directly call model.orgPerson versus just model.

Updated route:

actions: {
    willTransition: function( transition ) {
        this.controller.get('model.orgPerson').then( function( value ) {
            if ( value.get('isDirty') ) {
                value.rollback(); 
            }
        });
    }
}

  • Going forward, I just want to call this.controller.get('model').rollback(), so I'm going to write a util function that traverses eachRelationship and then individually calls rollback() on any of the objects. Whew, a lot of subtlety to get this working right.

解决方案

Ember Data stores the original values in the data obj. It stores modified values in _attributes obj. During a save it moves _attributes obj to inFlightAttributes obj, then after the save is complete it merges them from inFlightAttributes to data. All of this is so you can rollback your record.

When you define a property as attr it hooks up the magical get where it first checks _attributes, then inFlightAttributes, then data and returns that property's result.

function getValue(record, key) {
  if (record._attributes.hasOwnProperty(key)) {
    return record._attributes[key];
  } else if (record._inFlightAttributes.hasOwnProperty(key)) {
    return record._inFlightAttributes[key];
  } else {
    return record._data[key];
  }
}

https://github.com/emberjs/data/blob/v1.0.0-beta.8/packages/ember-data/lib/system/model/attributes.js#L267

In your case, Ember Data doesn't know you are saving that record, and you are manually grabbing the old properties from the data obj. You'd either need to manually merge _attributes to data or trick Ember Data into thinking you'd saved it.

这篇关于调用myModel.save()返回过时的模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆