I'm learning Ember Data now and I've experienced one issue that I cannot resolve without writing ugly code (this my own project so I have a time to do my best). The problem is: I have a 3 models: Post, User and Comment. Code will describe better what I mean ;)
/* 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== */
With the second variant, I'm having user/post id's instead of objects in the preview data when I'm perform saving - may be I don't understand right how to use it. Please, help me with this if you had similar experience.
Updated
When I'm making request using first variant - ERR:Net Error - too many redirect
When I'm making the request using the second variant:
1) It seems that DS.ActiveModelSerializer doesn't work at all
2) In the request there user_id and post_id, instead of embedded objects, actually it doesn't mean for me - to send embedded object or id, only thing about I care is to updated related models.
consider the screenshot for better understanding
And of course, after such saving it doesn't include saving the comment in the post.get("comments") and user.get("comments") properties.
P.S. I'm also have searched google for a very long time and haven't got response on my question, so please, do not answer if you aren't confident in your answer - thanks for understanding
==============================================================================================
After several hours of suffering, I've come up with this:
//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!
As you can see I'm updating only 1 related model - Post, I can't update User model due to the :Too-many redirections: error(I have bi-directional link between Post and Comment, and unidirectional link with User (Comment belongsTo User), I can't take comments that have User in the comments property). So far it's impossible. Also, I'm really saddened about DS.EmbeddedRecordMixin :( I won't close this topic until finding the answer on my question, however - thanks for helping!