简体   繁体   中英

deleteRecord with multiple belongsTo relationships in ember-cli

What is the ember-cli best practice to deleteRecord() on a model that belongsTo multiple models? Do I have to manually clean up relationships on the parents?

Migrating from ember to ember-cli I am having new trouble with deleteRecord() for a model 'star' that belongsTo multiple models, 'post' and 'user'. Before moving to ember cli it was working with this solution .

The previous solution's delete action fails in the current ember-cli with errors and never calls the api . TypeError: Cannot read property 'modelFor' of undefined and Uncaught Error: Assertion Failed: TypeError: Cannot read property 'modelFor' of undefined at the line

var inverse = relationship.parentType.inverseFor(name);
// name is the string 'post'

Now I'm starting simple again. Here is a simple example of what I'm trying. Maybe I am missing something with es6, explicit inverses, or using needs: ?

http://localhost:4200/post/1

子模型上的deleteRecord()无法清除父关系

models

// models/star.js
import DS from 'ember-data';

export default DS.Model.extend({
  created: DS.attr('date'),
  post: DS.belongsTo('post', {
    async: true,
    inverse: 'stars'
  }),
  user: DS.belongsTo('user', {
    async: true,
    inverse: 'stars'
  })
});


// models/post.js
import DS from 'ember-data';

export default DS.Model.extend({
  headline: DS.attr(),
  body: DS.attr(),
  stars: DS.hasMany('star', { async: true })
});


// models/users.js
import DS from 'ember-data';

export default DS.Model.extend({
  username: DS.attr(),
  stars: DS.hasMany('star', { async: true })
});

controller

//controllers/post.js
import Ember from 'ember';

export default Ember.ObjectController.extend({
  actions: {
    createStar: function(){
      var self=this,
          post = this.get('model'),
          user = this.store.find('user', 2),
          star;

      user.then( function(user){
        star = self.get('store').createRecord('star', {
          post: post,
          user: user
        });
        star.save().then( function(star){
          post.get('stars').then( function(stars){
            stars.pushObject(star);
          });
          user.get('stars').then( function(stars){
            stars.pushObject(star);
          });
        });
      });

    },
    deleteStar: function() {
      var user = this.store.find('user', 2),
          self = this;

      user.then( function(user){
        var filtered = self.get('stars').filterProperty('user.id', user.id);
        var star = filtered[0];

        star.deleteRecord();
        star.save();
      });
      return(false);
    }
  }
});

Update: Alternate deleteStar post controller action re: @jjwon

deleteStar: function() {
  var user = this.store.find('user', 2),
      self = this;

  user.then( function(user){

    var stars = self.get('stars').then( function(items){

      // log the post's stars before delete
      items.forEach(function(item) {
        console.log(item);
      });

      var filtered = items.filterBy('user.id', user.id);
      var star = filtered.get('firstObject');

      star.deleteRecord();
      star.save().then(function(){

        // log the post's stars after delete
        items.forEach(function(item) {
          console.log(item);
        });
      }); 
    });
  });
  return(false);
}

Interestingly I found that if I add a star, reload the page, then delete it, that the star is successfully removed from the post's stars. Great!

But if I add a star and remove it without reloading, there is still a reference to the removed star with its id among the post's stars. Looking in the console, the removed star object is still referenced by the post with its id , but the user and post attributes are undefined .

stars is an async attribute of user . Therefore, when you have:

var filtered = self.get('stars').filterProperty('user.id', user.id);
var star = filtered[0];

star.deleteRecord();
star.save();

filtered might be a promise, so this might not be working as expected. Also, I'm not too familiar with filterProperty, but you don't have an attribute called user.id so it seems like that might be returning an empty list?

For now I'm cleaning up the relationships on the parents very manually. This works but isn't ideal.

deleteStar: function() {
  var user = this.store.find('user', 2),
      self = this;

  user.then( function(user){
    var star = self.get('stars').filterBy('user.id', user.id).get('firstObject');

    // clean up relationships on parents very manually 
    // user.stars
    user.get('stars').removeObject(star);
    // posts.stars
    self.get('stars').removeObject(star);

    star.deleteRecord();
    star.save();

  });
  return(false);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM