【问题标题】:Ember Data. Save model with "belongsTo" relationship灰烬数据。保存具有“belongsTo”关系的模型
【发布时间】:2014-09-01 07:36:09
【问题描述】:

我现在正在学习 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 而不是对象 - 可能是我不明白如何正确使用它。如果您有类似的经历,请帮助我。

更新

当我使用第一个变体发出请求时 - ERR:Net Error - 重定向过多

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

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

当然,在这样的保存之后,它不包括在 post.get("cmets") 和 user.get("cmets") 属性中保存评论。

附:我也在google搜索了很长时间,也没有得到我的问题的回复,所以如果您对自己的答案没有信心,请不要回答-感谢理解

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

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

//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 相关模型 - 发布,由于以下原因,我无法更新 User 模型:重定向过多:错误(我在 Post 和 Comment 之间有双向链接,以及与 User 的单向链接(Comment belongsTo User),我不能接受在 cmets 属性中有 User 的 cmets)。到目前为止,这是不可能的。另外,我对 DS.EmbeddedRecordMixin 感到非常难过 :( 但是,在找到我的问题的答案之前,我不会关闭这个话题 - 感谢您的帮助!

【问题讨论】:

  • 我猜第二个变种没问题。您可以在此链接中查看github.com/emberjs/data/blob/master/…保存单个记录,基本上通过传递userId的方式相同。希望对你有帮助
  • 哇!这让我大开眼界……但是我需要检查一下。很快就会写下我的反馈。谢谢!
  • 但是,它并不能解决一次更新2个相关模型的问题
  • 对于嵌入对象,使用DS.EmbeddedRecordsMixin。我认为使用默认的 Ember Data 行为通常更可取,请考虑仅使用 ID 更新模型,如果它不起作用,则使用 DS.EmbeddedRecordsMixin
  • 自从我上次发表评论以来,我一直在做 ember 工作,所以我想我会用这些新知识发表评论。你说“使用第二个变体,当我执行保存时,我在预览数据中使用用户/帖子 ID 而不是对象” - 这是正确的。 hasMany 和属于在另一个模型上保存为 id。评论有一个用户 ID,这就是它们与用户的关系。等等。您没有将评论保存给用户,您只需创建三倍的开销,保存评论,将评论保存给用户,然后保存到帖子。相反,您通过 id 链接它。你的截图应该是这样的。

标签: ember.js ember-data


【解决方案1】:

@Craicerjack,

好吧,这可能有点令人困惑——我对这些事情的解释方式:)

我会尽量简化:我们有 3 个模型:PostUserCommentPost 有很多 Comment(s),User 有很多 Comment(s) 和 Comment 属于 PostComment 属于 User。这就是模型配置所描述的内容,很简单,但清楚地理解它很重要。

现在,(对我来说)困难的部分:我们要发表评论!创建记录,comment.save() 生成对服务器的 ajax 调用(post 类型)。我们的评论对象包含commentTextcreatedAt 和“链接/引用/关系”到相关模型 - post_iduser_id -

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

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

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

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

我们需要完成我们的帖子更新的最后一件事是通知服务器这件事,我们只是在做post.save()! :) 就是这样!

但是,如果我们想以同样的方式更新 User 模型我们会遇到:TOO_MANY_REDIRECTS: 错误,仅此而已......我们不能在添加评论的范围(时间)内这样做......

2015 年 1 月 1 日更新

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

【讨论】:

    【解决方案2】:
    /* 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== */
    

    【讨论】:

    • 感谢您的回答,但是我对这种方法有疑问:1)您建议两次保存评论模型(可能是输入错误),这会导致:TOO MANY REDIRECTIONS:错误; 2) 一般:comment.set('user', user),没有更新相关模型。保存评论模型后,您还应该保存与其关系相关的模型 - 用户和帖子模型
    • 这行得通吗?在评论中设置帖子然后添加用户关系?上面编辑的答案
    • 它不会改变任何东西! :) 您将保存与用户和帖子相关的评论,但用户和帖子没有关于评论的信息!
    • 一旦您保存评论,它就有关系并且应该可以通过该关系访问。 var user_id = this.get('user').id; var userComments = this.get('comments').filterBy('user', user_id);
    • 你到底想做什么?看起来这个问题的解决方案应该是“相对”简单的。
    猜你喜欢
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    相关资源
    最近更新 更多