Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to persist child model with Ember.js?

Problem

I'm teaching myself Ember and having problems persisting my child models. Here's a JSBin that demonstrates the problem:

http://jsbin.com/OnUXEti/2/edit?html,js,output

If you play with it, you will be able to create Posts and Comments, but only the Posts are still available after a page reload. (I'm using ember-data and the localStorage adapter)


There are two model types, Post and Comment

App.Post = DS.Model.extend({
  title: DS.attr('string'),
  comments: DS.hasMany('comment')
});

App.Comment = DS.Model.extend({
  message: DS.attr('string')
});

Each Post has an array of Comments. I intend there to be the following URLs:

  • /posts will list all the Posts
  • /posts/1 will display the Post with id 1
  • /posts/1/comments will display the Comments for Post 1

Routes are defined like so:

App.Router.map(function() {
  this.resource("posts", { path: "/posts" });
  this.resource("post", { path: "/posts/:post_id" }, function() {
    this.resource("comments", { path: "/comments" });
  });
});

I am able to write Post models to the store without problem. What I cannot do is save the Comment models. If you play with my JSBin example above you will see that you can create comments but they are not persisted when reloading the page.

I attempt to save Comments in the CommentsController:

App.CommentsController = Ember.ArrayController.extend({
    needs: "post",
    post: Ember.computed.alias("controllers.post"),
    newMessage: '',
    actions: {
        create: function() {
            var message = this.get('newMessage');

            var comment = this.store.createRecord('comment', {
                message : message
            });

            this.set('newMessage', '');

            var post = this.get('post');
            var comments = post.get('comments');
            comments.pushObject(comment);
            comment.save();
        }
    }
});

Notice that I am getting a handle on the parent Post by using the needs property. Taken from the documentation about dependencies between controllers.

This all feels wrong as it should be a common situation so I suspect I've designed my models or routes in a non-standard way.

Thanks, Matt

like image 924
matt burns Avatar asked Sep 13 '13 18:09

matt burns


1 Answers

The issue here is that you need to save the post after adding the comment to its comments collection. It looks like the LSAdapter stores the array of comment ids directly in the post record.

Here's a modified JSBin : http://jsbin.com/OnUXEti/8/edit

Note: I also changed this :

post: Ember.computed.alias("controllers.post")

to this:

post: Ember.computed.alias("controllers.post.model")

In order to save the post you want to be dealing with the actual model, not the controller.

I also had to update Ember Data and the LSAdapter to get things to work, and I changed the hasMany relationship on comments to be async.

comments: DS.hasMany('comment',{async:true})

[UPDATE] : I originally posted the wrong JSBin. The correct one is : http://jsbin.com/OnUXEti/8/edit

like image 156
Jeremy Green Avatar answered Oct 03 '22 00:10

Jeremy Green