【问题标题】:Ember Data: model and hasMany submodels not persistingEmber 数据:模型和 hasMany 子模型不持久
【发布时间】:2014-06-13 19:25:09
【问题描述】:

我有一个类似于this stack overflow question 的问题,除了答案似乎不起作用。我有一个表单,用户在其中创建具有可变数量子模型的容器模块。提交表单时,我必须保存容器、子模型,并确保 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 Data 本身工作正常,转换到创建的容器的视图,并列出了子模型。刷新页面,子模型从容器视图中消失。

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

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

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

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

【问题讨论】:

  • 请您标注导出的路由/控制器是什么?当您刚刚获得出口时,很难猜测事情是如何相关的。谢谢!
  • 请您也包括模型定义吗?

标签: javascript ember.js ember-data ember-cli


【解决方案1】:

问题

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

更多信息

请阅读Embedded Records Mixin section on A Thorough Guide to Ember Data 了解更多信息。 (免责声明,我是它的作者。)

这是摘录

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

您可以选择:

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

代码示例:

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

【讨论】:

    【解决方案2】:

    你有我之前遇到的问题,你有比我更简单的例子,因为你只需要一个关系: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');
        }
     }
    });
    

    祝你好运;)

    【讨论】:

      猜你喜欢
      • 2013-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多