调用myModel.save()返回过时的模型

时间:2014-08-17 11:34:07

标签: ember.js ember-data

我正在尝试在更新后保存Ember数据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(见下文),因此embedded: 'always'的唯一用途是我的自定义RESTSerializer如何处理它。

/models/OrgPerson.js:

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

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

/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);
        }
    }
})

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

/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
         ...
        }
    }
});

我知道为什么我会得到同一型号的两个不同版本?如何序列化正确更新的模型?感谢您的任何意见!

SOLUTION:

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

  • 我的序列化程序实际上是问题,并使用了Ember的旧保存数据。我将行data[relationship.key].get('data')替换为行data[relationship.key].serialize(),这是固定的。
  • 然后我遇到了另一个问题,那就是如果我编辑了我的记录,没有保存它,然后回到我的记录列表,列表仍显示编辑。我的第一个想法是我需要更新我的列表页面model以仅显示最新内容,但似乎没有任何Ember工具。
  • 所以我最终通过在我的路线中使用以下代码解决了这个问题。请注意,因为orgPersonasync: true,我必须将我的模型包装在一个承诺中。另请注意,我必须直接致电model.orgPerson而不是model

更新路线:

actions: {
    willTransition: function( transition ) {
        this.controller.get('model.orgPerson').then( function( value ) {
            if ( value.get('isDirty') ) {
                value.rollback(); 
            }
        });
    }
}
  • 前进,我只想打电话给this.controller.get('model').rollback(),所以我要写一个遍历eachRelationship的util函数,然后在任何一个对象上单独调用rollback() 。哇,这很有道理,让这个工作正常。

1 个答案:

答案 0 :(得分:2)

Ember Data将原始值存储在data obj中。它将修改后的值存储在_attributes obj中。在保存期间,它将_attributes obj移动到inFlightAttributes obj,然后在保存完成后将它们从inFlightAttributes合并到data。所有这些都是你可以回滚你的记录。

当您将某个属性定义为attr时,它会将首先检查_attributes,然后inFlightAttributes,然后data的魔法获取连接起来并返回该属性'结果。

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

在您的情况下,Ember Data不知道您正在保存该记录,而您是从data obj手动抓取旧属性。您需要手动将_attributes合并到data或欺骗Ember数据,以为您已将其保存。