7

我有一个类似于这个堆栈溢出问题的问题,除了答案似乎不起作用。我有一个表单,用户在其中创建具有可变数量子模型的容器模块。提交表单时,我必须保存容器、子模型,并确保 hasMany 关系仍然存在。我的代码(使用 Ember-Cli):

容器

var Container= DS.Model.extend({
    name: DS.attr('string'),
    submodels: DS.hasMany('submodel'),
    lastModified: DS.attr('date')
});

export default Container;

子型号:

    var Submodel= DS.Model.extend({
        char: DS.belongsTo('container'),
        name: DS.attr('string'),
        desc: DS.attr('string'),
        priority: DS.attr('number'),
        effort: DS.attr('number'),
        time: DS.attr('number')
    });

export default Submodel;

ContainersNewRoute:

 export default Ember.Route.extend({
        model: function() {
            return this.store.createRecord('container', {
                ...
            });
        }
    });

ContainersNewController:

export default Ember.ObjectController.extend({
    actions: {
        addSubmodel: function() {
            var submodels= this.get('model.submodels');

            submodels.addObject(this.store.createRecord('submodel', {
                ...
            }));
        },
        saveNewContainer: function () {
            var container = this.get('model');

            container.save().then(function(){
                var promises = Ember.A();
                container.get('submodels').forEach(function(item){
                    promises.push(item.save);
                    console.log(item);
                });
                Ember.RSVP.Promise.all(promises).then(function(resolvedPromises){
                    alert('all saved');
                });
            });

            this.transitionToRoute(...);
        }
    }
});

Ember 数据本身工作正常,转换到创建的容器的视图,并列出了子模型。刷新页面,子模型从容器视图中消失。

我尝试了一些变体,例如使用 pushObject 而不是堆栈溢出答案中的 addObject 。我还尝试使用 Ember.RSVP 回调在保存子模型后第二次运行 container.save()。

经过一些进一步的测试,我发现子模型根本没有持久化。

有没有一种理智的方法来保存 1)容器 2)子模型 3)hasMany/belongsTo 相互关系?

或者这是否需要分解成离散的步骤,我保存容器,保存子模型,将子模型推送到容器以获取 hasMany 关系并重新保存容器,最后使子模型属于容器并保存又是子模型?

4

2 回答 2

6

问题

默认情况下,DS.hasMany一对多关联ids在序列化时不会包含字段。您可以使用DS.EmbeddedRecordsMixin来更改此行为。

更多信息

请阅读Ember 数据全面指南中的 Embedded Records Mixin 部分了解更多信息。(免责声明,我是它的作者。)

这是摘录

DS.EmbeddedRecordsMixin是一个扩展DS.ActiveModelSerializer,允许配置关联如何被序列化或反序列化。虽然还没有完成(特别是关于多态关联),但它仍然很有趣。

您可以选择:

  • 不要序列化或反序列化关联。
  • 序列化或反序列化与 id 或 ids 的关联。
  • 序列化或反序列化与嵌入式模型的关联。

代码示例:

App.CartSerializer = DS.ActiveModelSerializer
                       .extend(DS.EmbeddedRecordsMixin)
                       .extend{
                         attrs: {
                           items: {serialize: 'ids', deserialize: 'ids'}
                         }
                       });

App.Cart = DS.Model.extend({
  items: DS.hasMany('item', {async: true})
});

App.Item = DS.Model.extend({
  cart: DS.belongsTo('item', {async: true})
});
于 2014-06-23T18:09:27.220 回答
1

你有我之前遇到的问题,你有比我更简单的例子你只需要一个关系:hasMany 和 :belongsTo

尝试使用这种方法:

export default Ember.ObjectController.extend({
// here we can pre-load submodels container, 
//even if it's empty because 'this.get('model.submodels')' returns promise

submodels: function () { 
    return this.get('model.submodels');
}.property('model.@each.submodels'),

actions: {
    addSubmodel: function () {
        //saving context of controller, saving container for 
        //better understanding (clear vision)
        var controller = this, 
            container = controller.get('conrtainer');
        //container  instead of 'model' for better understanding :)

        //1. Creating submodel
        var submodel = this.get('store').createRecord('submodel', {
            // ... //
            container: container
        });

        //2. Saving submodel
        submodel.save().then(function (submodel_res) {

            //3. It isn't the end though :) 
            //Now we're getting our submodels from the container - here we will get
            //the result instead of promise, remember we pre-loaded it :) -1 nesting lvl
            controller.get("submodels").pushObject(submodel_res);

            //4. Now we need to update our 'parent' model - Container
            container.save().then(function (post_res) {
                console.log(post_res); // 5. Doesn't matter we are happy
            }, function (err) {
                console.log(err);
            });
        }, function (err) {
            console.log(err);
        });
      }
   }
});

 //In order to use this approach you need to override property 
 //in model serializer (just copy it    and //paste :) )

 YourApp.ContainerSerializer = DS.ActiveModelSerializer.extend({ 
 // here coulbe be RESTSerializer as well ;)

 primaryKey: function () {
    return '_id';
 }.property(), 
 // it's just helpful tip, if you use mongo like me ;) 
 //it doesn't relates to the main topic itself

 // this little method will help you update 'parent' model ;)
 serializeHasMany: function (record, json, relationship) { 
    var key = relationship.key;
    var json_key = key.singularize().decamelize() + '_ids';

    var relationshipType = DS.RelationshipChange.determineRelationshipType(
        record.constructor, relationship);

    if (relationshipType === 'manyToNone' 
    || relationshipType === 'manyToMany' 
    || relationshipType === 'manyToOne') {
        json[json_key] = Ember.get(record, key).mapBy('id');
    }
 }
});

祝你好运 ;)

于 2014-07-14T20:38:27.613 回答