Ember Data: model and hasMany submodels not saved

I have a problem similar to this question , except that the answer does not seem to work. 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, submodels and make sure that hasMany relationships are saved. 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(...); } } }); 

Ember Data itself works fine, moving on to presenting the created container with the listed submodels. Refresh the page and the submodels will disappear from the container view.

I tried several options, for example using pushObject, and not addObject from the response to a stack overflow. I also tried using the Ember.RSVP callback to run container.save () a second time after saving the submodels.

After some additional testing, I found that submodels are not saved at all.

Is there any reasonable way to save 1) a container 2) submodels 3) hasMany / belongs to relationships with each other?

Or does it somehow need to be broken down into discrete steps when I save the container, save the submodels, click the submodels in the container to get the hasMany relationships and recreate the container, and finally make the submodels belong to the container and save the submodels again?

+7
javascript ember-cli ember-data
source share
2 answers

Problem

By default, DS.hasMany in one association will not include the ids field during serialization. You can use DS.EmbeddedRecordsMixin to change this behavior.

More details

Please read the Embedded Records Mixin section of the Ember Data Guide for more information. (disclaimer, I am its author).

Here is an excerpt

DS.EmbeddedRecordsMixin is an extension for DS.ActiveModelSerializer that allows you to customize how associations become serialized or deserialized. Although it is not yet complete (especially regarding polymorphic associations), it is nonetheless intriguing.

You can choose:

  • Not for serialization or deserialization of associations.
  • Serialize or deserialize associations with identifiers or identifiers.
  • Serialize or deserialize associations with built-in models.

Code example:

 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}) }); 
+6
source share

You have a problem that I encountered earlier, you have a simpler example than my argument. You need only one relationship: hasMany and: belongsTo

Try using this approach:

 export default Ember.ObjectController.extend({ // here we can pre-load submodels container, //even if it 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 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;)

+1
source share

All Articles