【问题标题】:Ember Data belongsTo async relationship omitted from createRecord() save() serialization从 createRecord() save() 序列化中省略 Ember Data belongsTo 异步关系
【发布时间】:2014-11-14 23:11:56
【问题描述】:

编辑 11/16/14:版本信息

DEBUG: Ember      : 1.7.0 ember-1.7.0.js:14463
DEBUG: Ember Data : 1.0.0-beta.10+canary.30d6bf849b ember-1.7.0.js:14463
DEBUG: Handlebars : 1.1.2 ember-1.7.0.js:14463
DEBUG: jQuery     : 1.10.2 

我正在努力做一些我认为应该相当直接使用 ember 和 ember-data 的事情,但到目前为止我还没有运气。

基本上,我想使用服务器数据来填充<select> 下拉菜单。提交表单时,应根据用户选择的数据创建模型。然后将模型与 ember 数据一起保存并以以下格式转发到服务器:

{ 
    "File": { 
        "fileName":"the_name.txt",
        "filePath":"/the/path",
        "typeId": 13,
        "versionId": 2
    }
}

问题是,当模型关系被定义为异步时,typeId 和 versionId 被遗漏了:

App.File =  DS.Model.extend({
    type: DS.belongsTo('type', {async: true}),
    version: DS.belongsTo('version', {async: true}),
    fileName: DS.attr('string'),
    filePath: DS.attr('string')
});

让我困惑的部分,也可能是我的错误所在,是控制器:

App.FilesNewController = Ember.ObjectController.extend({
    needs: ['files'],
    uploadError: false,

    // These properties will be given by the binding in the view to the 
    //<select> inputs.  
    selectedType: null,
    selectedVersion: null,

    files: Ember.computed.alias('controllers.files'),

    actions: {
        createFile: function() {
            this.createFileHelper();
        }
    },

    createFileHelper: function() {
        var selectedType = this.get('selectedType');
        var selectedVersion = this.get('selectedVersion');

        var file = this.store.createRecord('file', {
                fileName: 'the_name.txt',
                filePath: '/the/path'
        });

        var gotDependencies = function(values) {

            //////////////////////////////////////
            // This only works when async: false
            file.set('type', values[0])
                .set('version', values[1]);
            //////////////////////////////////////

            var onSuccess = function() {
                this.transitionToRoute('files');
            }.bind(this);

            var onFail = function() {
                this.set('uploadError', true);
            }.bind(this);

            file.save().then(onSuccess, onFail);
        }.bind(this);

        Ember.RSVP.all([
            selectedType,
            selectedVersion
        ]).then(gotDependencies);
    }
});

当 async 设置为 false 时,ember 会正确处理 createRecord().save() POST 请求。

当 async 为 true 时,ember 可以完美地处理多个请求的 GET 请求,但不会在 createRecord().save() 期间将 belongsTo 关系添加到文件 JSON 中。仅对基本属性进行序列化:

{"File":{"fileName":"the_name.txt","filePath":"/the/path"}}

我知道以前有人问过这个问题,但到目前为止我还没有找到满意的答案,也没有找到任何适合我需要的东西。那么,如何让belongsTo 关系正确序列化?

为了确保一切都在这里,我将添加到目前为止的自定义序列化:

App.ApplicationSerializer = DS.RESTSerializer.extend({
    serializeIntoHash: function(data, type, record, options) {
        var root = Ember.String.capitalize(type.typeKey);
        data[root] = this.serialize(record, options);
    },
    keyForRelationship: function(key, type){
        if (type === 'belongsTo') {
            key += "Id";
        }
        if (type === 'hasMany') {
            key += "Ids";
        }
        return key;
    }
});

App.FileSerializer = App.ApplicationSerializer.extend(DS.EmbeddedRecordsMixin, {
    attrs: {
        type: { serialize: 'id' },
        version: { serialize: 'id' }
    }
});

还有一个选择:

{{ view Ember.Select
    contentBinding="controller.files.versions"
    optionValuePath="content"
    optionLabelPath="content.versionStr"
    valueBinding="controller.selectedVersion"
    id="selectVersion"
    classNames="form-control"
    prompt="-- Select Version --"}}

如有必要,我将附加其他路由和控制器(FilesRoute、FilesController、VersionsRoute、TypesRoute)

编辑 2014 年 11 月 16 日

我根据两个相关线程中的信息找到了一个可行的解决方案(hack?):

1) How should async belongsTo relationships be serialized?

2) Does async belongsTo support related model assignment?

基本上,我所要做的就是将Ember.RSVP.all() 移到属性上的get() 之后:

createFileHelper: function() {
    var selectedType = this.get('selectedType');
    var selectedVersion = this.get('selectedVersion');

    var file = this.store.createRecord('file', {
            fileName: 'the_name.txt',
            filePath: '/the/path',
            type: null,
            version: null
    });


    file.set('type', values[0])
        .set('version', values[1]);

    Ember.RSVP.all([
        file.get('type'),
        file.get('version')
    ]).then(function(values) {

        var onSuccess = function() {
            this.transitionToRoute('files');
        }.bind(this);

        var onFail = function() {
            alert("failure");
            this.set('uploadError', true);
        }.bind(this);

        file.save().then(onSuccess, onFail);
    }.bind(this));
}

所以我需要在保存模型之前get() 属于属于关系的属性。我不知道这是否是一个错误。也许对 emberjs 有更多了解的人可以帮助阐明这一点。

【问题讨论】:

  • 我刚刚遇到了同样的问题。有更新吗?
  • @torazaburo 在您要求承诺之前,您是 .get()ing 属性吗?即set() 他们,然后在.get() 上使用.all().then()。看我的回答。
  • 是的,我正在做 set 然后 get(...).then(...) 并且它正在工作,但这似乎被严重破坏了,我想知道你是否能想出一些更“优雅”的东西,在某种程度上Ember 永远优雅。实际上我并没有做一个单独的set,而是将哈希中的值传递给createRecord

标签: javascript ember.js ember-data rsvp-promise


【解决方案1】:

有关更多详细信息,请参阅问题,但我在保存具有 belongsTo 关系的模型时为我工作的通用答案(并且您特别需要序列化该关系)是在属性上调用 .get() 然后 @ 987654322@他们在then()

归结为:

var file = this.store.createRecord('file', {
        fileName: 'the_name.txt',
        filePath: '/the/path',
        type: null,
        version: null
});

// belongsTo set() here
file.set('type', selectedType)
    .set('version', selectedVersion);

Ember.RSVP.all([
    file.get('type'),
    file.get('version')
]).then(function(values) {

    var onSuccess = function() {
        this.transitionToRoute('files');
    }.bind(this);

    var onFail = function() {
        alert("failure");
        this.set('uploadError', true);
    }.bind(this);

    // Save inside then() after I call get() on promises
    file.save().then(onSuccess, onFail);

}.bind(this));

【讨论】:

    猜你喜欢
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多