Ember数据。使用“belongsTo”关系保存模型

时间:2014-07-10 19:32:33

标签: ember.js ember-data

我现在正在学习Ember Data,而且我遇到了一个问题,如果不编写丑陋的代码我就无法解决(这是我自己的项目所以我有时间尽我所能)。问题是: 我有3个模型:帖子,用户和评论。代码将更好地描述我的意思;)

/* Post Model */

    Blog.Post = DS.Model.extend({
      title: DS.attr('string'),
      text: DS.attr('string'),
      postedAt: DS.attr('string', { defaultValue: new Date() }),
      comments: DS.hasMany("comment", { async: true })
    });

/* ==Post Model== */

/* User Model */

    Blog.User = DS.Model.extend({
      name: DS.attr('string'),
      avatar: DS.attr('string'),
      comments: DS.hasMany("comment", { async: true })
    });

/* ==User Model== */

/* Comment Model */

    Blog.Comment = DS.Model.extend({
        title: DS.attr("string"),
        text: DS.attr("string"),
        user: DS.belongsTo("user", { async: true }),
        post: DS.belongsTo("post", { async: true }),
        postedAt: DS.attr("date", { defaultValue: new Date() })
    });

/* ==Comment Model== */

/* Post Controller (bad variant and it doesn't work - too many redirects error) */

    leaveComment: function () {
        var controller = this, 
            user = controller.get('user'), 
            post = controller.get('model');
        var comment = this.get('store').createRecord('comment', {
              title: controller.get('commentTitle'),
              text:  controller.get('commentText'),
              user:  user,
              post:  post
            });
        comment.save().then(function (res) {
                controller.setProperties({
                    commentTitle: "",
                    commentText : ""
                });
                user.get("comments").then(function (comments) {
                    comments.pushObject(comment);
                    user.save().then(function (ures) {
                        console.log(ures);
                        post.get("comments").then(function (comments) {
                            comments.pushObject(comment);
                            post.save().then(function (pres) {
                                console.log(pres)
                            }, function (err) {
                                console.log(err);
                            });
                        });
                    }, function (err) {
                        console.log(err);
                    })
                });



            }, function (err) {
                console.log(err);
            });

/* ==Post Controller== */

/* Post Route */

Blog.PostRoute = Ember.Route.extend({
    setupController: function (controller, model) {
        this._super(controller, model);
        controller.setProperties({
            user: this.modelFor('application')
        });
    },
    model: function(params) {
        return this.store.find('post', params["post_id"]);
    }
});

/* ==Post Route== */

/* 2nd variant */

   /* Post Controller */
        leaveComment: function () {
            var controller = this, 
            user = controller.get('user'), 
            post =   controller.get('model');
            var comment = this.get('store').createRecord('comment', {
                title: controller.get('commentTitle'),
                text:  controller.get('commentText'),
                user:  user,
                post:  post
            });
            comment.save().then(function (res) {}, function(err) { console.log(err) });

    /* ==Post Controller== */

   /* Application.js */

      Blog.CommentSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
        primaryKey: function() {
            return '_id';
        }.property(),
        attrs: {
            user: { embedded: 'always' },//{serialize: 'id', deserialize: 'id'},
            post: { embedded: 'always' }//{serialize: 'id', deserialize: 'id'}
        }
      });

   /* ==Application.js== */

使用第二个变体,当我执行保存时,我在预览数据中有用户/帖子ID而不是对象 - 可能我不明白如何使用它。如果你有类似的经历,请帮助我。

更新

当我使用第一个变体发出请求时 - 错误:网络错误 - 重定向太多

当我使用第二个变体发出请求时:

1)似乎DS.ActiveModelSerializer根本不起作用 2)在请求中有user_id和post_id,而不是嵌入对象,实际上对我来说并不意味着 - 发送嵌入对象或id,只关心我关心的是更新相关模型。 考虑屏幕截图以便更好地理解 Request using 2nd variant

当然,在保存之后,它不包括在post.get(“comments”)和user.get(“comments”)属性中保存注释。

P.S。我也搜索谷歌很长一段时间没有得到我的问题的回复,所以请不要回答,如果你对你的答案没有信心 - 感谢理解

=============================================== ===============================================

经过几个小时的痛苦,我想出了这个:

//Controller
comments: function () {
    return this.get('model.comments')
}.property('model.@each.comments'),
post: function () {
    return this.get('model');
}.property('post'),
user: function () {
    return this.get('user');
}.property('user'),
actions: {
  leaveComment: function () {
        var controller = this, 
        user = controller.get('user'), 
        post = controller.get('post');
        var comment = this.get('store').createRecord('comment', {
            text: controller.get('commentText'),
            user: user,
            post: post,
            postedAt: new Date()
        });
        comment.save().then(function (comment_res) {
            controller.get("comments").pushObject(comment_res);
            post.save().then(function (post_res) {
                controller.set("commentText", "");
            }, function (err) {
                console.log(err);
            });
        }, function (err) {
            console.log(err);
        });
    }
 }

    Blog.CommentSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
      primaryKey: function () {
        return '_id';
      }.property()//,
      //attrs: {//{ embedded: 'always' },
      //  user: { embedded: 'always' }, //{serialize: 'id', deserialize: 'id'},
      //  post: { embedded: 'always' } //{serialize: 'id', deserialize: 'id'}
      //} // <-this doesn't work :\ 
    });

    Blog.PostSerializer = DS.ActiveModelSerializer.extend({
      primaryKey: function () {
        return '_id';
      }.property(),
      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');
        }
     }// <- And this really works!

正如您所看到我只更新 1 相关型号 - 发布,我无法更新用户模型,因为:太多的重定向:错误(我在Post和Comment之间有双向链接,与User的单向链接(Comment belongsTo User),我不能在comments属性中带有User的注释)。到目前为止,这是不可能的。另外,我对 DS.EmbeddedRecordMixin 感到非常难过:(在找到我的问题的答案之前,我不会关闭这个主题,但是 - 感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

@Craicerjack,

嗯,这可能有点令人困惑 - 我解释这样的事情:)

我会尝试简化:我们有3个模型:PostUserCommentPostComment个,UserComment个,Comment属于PostComment属于User。这就是模型配置所描述的,很容易理解它,但很重要。

现在,很难(对我而言)部分:我们将发表评论!创建记录,comment.save()向服务器生成ajax调用(post类型)。我们的评论对象包含commentTextcreatedAt和&#34;链接/参考/关系&#34;相对模型 - post_iduser_id -

comment.save().then(function(responseFromSavedComment) { 
    // we will insert next steps here... 
}); 

这很好。现在我们需要更新我们的Post模型和User模型;我们刚刚添加了Comment,还记得吗?好!首先,我们将更新Post;我们需要提取post.get('comments'),返回Promise然后推送并反对其响应,对吧?

post.get('comments').then(function(postComments) {
    postComments.pushObject(responseFromSavedComment);
}); 

当我们发布评论本身时,我们只是将最近创建的评论推送到承诺解决范围内的帖子。明确?完善!

我们完成Post更新所需的最后一件事是通知服务器这个,我们只是做post.save()! :)那就是全部!

但是,如果我们想以同样的方式更新用户模型,我们会遇到:TOO_MANY_REDIRECTS:错误,那就是......我们无法在范围(时间)内执行此操作添加评论...

2015年1月1日更新

我找到了解决方案 - 不使用嵌入式记录:)服务器将获取密钥并执行所有操作。现在无法在客户端完全处理这个问题。

答案 1 :(得分:0)

/* Post Controller  */

leaveComment: function () {
    var user = this.get('user');
    var post = this.get('post');
    var comment = this.store.createRecord('comment', {
        title: this.get('commentTitle'),
        text:  this.get('commentText'),
        user:  user,
        post:  post
    });
    this.get('model').pushObject(comment);
    comment.save();
    };

/* ==Post Controller== */