【发布时间】: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