javascript - Ember Data: model and hasMany submodels not persisting - Stack Overflow

I have a problem similar to this stack overflow question, except the answer doesn't seem to be wor

I have a problem similar to this stack overflow question, except the answer doesn't seem to be working. I have a form in which the user creates a container module with a variable number of submodels. When the form is submitted, I have to save the container, the submodels, and make sure that the the hasMany relationship persists. My code (using Ember-Cli):

container:

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

export default Container;

submodel:

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

The Ember Data itself works fine, transition to a view of the created container, with submodels listed. Refresh the page, and the submodels disappear from the container view.

I've tried a few variations, for example using pushObject rather than the addObject from the stack overflow answer. I've also tried using the Ember.RSVP callback to run container.save() a second time after the submodels have been saved.

After some further testing, I've found that the submodels are not persisting at all.

Is there a sane way to save 1) the container 2) the submodels 3) the hasMany/belongsTo relationships to each other?

Or does this some how need to be broken down into discrete steps where I save the container, save the submodels, the push the submodels to the container to get the hasMany relationship and resave the container, and lastly make the submodels belongTo the container and save the submodels again?

I have a problem similar to this stack overflow question, except the answer doesn't seem to be working. I have a form in which the user creates a container module with a variable number of submodels. When the form is submitted, I have to save the container, the submodels, and make sure that the the hasMany relationship persists. My code (using Ember-Cli):

container:

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

export default Container;

submodel:

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

The Ember Data itself works fine, transition to a view of the created container, with submodels listed. Refresh the page, and the submodels disappear from the container view.

I've tried a few variations, for example using pushObject rather than the addObject from the stack overflow answer. I've also tried using the Ember.RSVP callback to run container.save() a second time after the submodels have been saved.

After some further testing, I've found that the submodels are not persisting at all.

Is there a sane way to save 1) the container 2) the submodels 3) the hasMany/belongsTo relationships to each other?

Or does this some how need to be broken down into discrete steps where I save the container, save the submodels, the push the submodels to the container to get the hasMany relationship and resave the container, and lastly make the submodels belongTo the container and save the submodels again?

Share Improve this question edited May 23, 2017 at 10:34 CommunityBot 11 silver badge asked Jun 13, 2014 at 19:25 ansorensenansorensen 1,3162 gold badges15 silver badges29 bronze badges 2
  • Will you please label what the exported routes/controllers are? It's difficult to guess how things are related when you just get an export. Thanks! – Kingpin2k Commented Jun 14, 2014 at 5:04
  • Will you also please include the model definitions? – Kingpin2k Commented Jun 14, 2014 at 5:15
Add a ment  | 

2 Answers 2

Reset to default 6 +50

The Problem

By default, DS.hasMany on a one to many association won't include ids field when serializing. You can use DS.EmbeddedRecordsMixin to change this behavior.

More Info

Please read Embedded Records Mixin section on A Thorough Guide to Ember Data for more. (disclaimer, I'm its author.)

Here is an excerpt

DS.EmbeddedRecordsMixin is an extension for DS.ActiveModelSerializer which allows configuring of how associations get serialized or deserialized. Although not yet plete (especially with regard to polymorphic associations), it is intriguing nonetheless.

You can choose:

  • Not to serialize or deserialize associations.
  • To serialize or deserialize associations with id or ids.
  • To serialize or deserialize associations with embedded models.

Code Sample:

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

You have the problem that I've experienced earlier, you have easier example than my cause you need only one relation :hasMany and :belongsTo

Try to use this approach:

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('[email protected]'),

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

Good luck ;)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745613942a4636116.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信