What is the best practice to persist many to many relationship


#1

I want to assign multiple tags to an article.

Here are my Models

App.Article = DS.Model.extend({
  title: DS.attr('string'),
  body: DS.attr('string')
  articleTags: DS.hasMany('articleTag', {async: true})
});

App.NewsArticle = App.Article.extend({
});

App.ArticleTag = DS.Model.extend({
  tag: DS.belongsTo('tag', {async: true}),
  article: DS.belongsTo('article', {async: true})
});

App.Tag = DS.Model.extend({
  title: DS.attr('string'),
  articleTags: DS.hasMany('articleTag', {async: true})
});

I’m using this apporach to persisting relationship between tags (persisted or not) and persisted article.

all articles’ class used in those approach is NewsArticle, not Article

  1. persist article using save()
  2. get article’s articleTags
  3. get each articleTag’s tag.
  4. persist those tags using save()
  5. persist article’s articleTags with save()

The code is like below.

  var article, tagPromiseArray, tagSavePromiseArray, articleTagsOfArticle;

  article = this.controller.get('model');

  article.save().then(function() {
    return article.get('articleTags');

  }.bind(this)).then(function(articleTags) {
    articleTagsOfArticle = articleTags;
    tagPromiseArray = articleTags.map(function(articleTag) {
      return articleTag.get('tag');
    }, this);

    return Ember.RSVP.all(tagPromiseArray)

  }.bind(this)).then(function(tags) {
    tagSavePromiseArray = tags.map(function(tag) {
      return tag.save();
    }, this);

    return Ember.RSVP.all(tagSavePromiseArray)

  }.bind(this)).then(function(tags) {
    return articleTagsOfArticle.save();
  }.bind(this)).then(function() {
    this.controller.set("flashSuccess", "Successfully modified.");
    this.transitionTo('index');  
    
  }.bind(this));

This works fine even though it use a lot of server request.

But it doesn’t work when I use this approach to not persisted article.

after I call article.save() on the new article, length of articleTags for the article become 0. so I think relationship is broken when I call article.save()… but why?

  article.get('articleTags').then(function(articleTags) {
       console.log(articleTags); // its length is 0 after I call article.save()
  })

So I did another apporach for persisting new article,

  1. get articleTag of the article

  2. get each articleTag’s tag

  3. persist those tags using save().

  4. get articleTag of the article once again

  5. persist them with seperate save() promises and assign return value to this.articleTagsThatShouldBeAssociatedWithArticle (because raw ‘articleTags’ recordArray gets empty after article.save() called)

  6. persist article using save()

  7. associate each articleTag in this.articleTagsThatShouldBeAssociatedWithArticle with article and persist them.

     article.get('articleTags').then(function(articleTags) {
       return this.getTagsFromArticleTags(articleTags)
     }.bind(this)).then(function(tags) {
       return this.saveTags(tags);
     }.bind(this)).then(function() {
       return article.get('articleTags');
     }.bind(this)).then(function(articleTags) {
       return this.saveArticleTags(articleTags);
     }.bind(this)).then(function(articleTags) {
       this.set('articleTagsThatShouldBeAssociatedWithArticle', articleTags);
       return article.save();
     }.bind(this)).then(function(article) {
       return this.associateArticleTagsWith(article);
     }.bind(this)).then(function() {
       this.controller.set('flashSuccess', 'Successfully created.');
       this.controllerFor('index').set('page', 1);
       this.transitionTo('index');
     }.bind(this));
    

but This doens’t work either. I checked my server log, and realized that when attempting to persist association between articleTags and article. my server request doesn’t include article_id… even though articleTag.set(‘article’, article) is properly set.

What am I doing wrong? What is the best practices for persisting many to many association?