Ember数据:模型和hasMany子模型不会持久化

时间:2014-06-13 19:25:10

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

我遇到类似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关系并重新保存容器,最后使子模型属于容器并再次保存子模型?

2 个答案:

答案 0 :(得分:6)

问题

默认情况下,序列化时,一对多关联中的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})
});

答案 1 :(得分: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');
    }
 }
});
祝你好运;)

相关问题