5

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

matt burns
  • 24,742
  • 13
  • 105
  • 107
  • I see the problem, i am trying out your fiddle... it seems your model is getting updated but your post model seems not get reflected... which is mapped to your comment objects... – Thalaivar Sep 14 '13 at 07:17
  • Take a look at this answer: http://stackoverflow.com/questions/15138219/ember-data-saving-a-relationship/15145803#15145803 – Thalaivar Sep 14 '13 at 07:22

1 Answers1

6

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

Jeremy Green
  • 8,547
  • 1
  • 29
  • 33
  • +1 : wow,, i did make changes to the post attribute, but did not change the relationship.... awesome... – Thalaivar Sep 15 '13 at 10:00
  • Thank you so much for your time! You are a scholar and a saint! Thanks to you I have realised that I had 2 problems: 1) I was not saving the 'post' model. 2) I needed to use ember-data-latest.js. I have created another JSBin that just does the minimum changes needed to get it to work. Note that I did not need to update LSAdapter nor did I set the 'async' option on my post model. http://jsbin.com/OnUXEti/17/edit?html,js,output If I could give you more points I would, I was about to give up on ember just as I was starting to love it :) Thanks again, Matt. – matt burns Sep 15 '13 at 13:13
  • 1
    Ahh, I needed the async option otherwise sometimes I would get the error: "Uncaught TypeError: Cannot read property 'resolve' of undefined". Thanks again! – matt burns Sep 18 '13 at 11:58
  • For me I needed async and I had not defined the serializer for my adapter: App.ApplicationSerializer = DS.LSSerializer.extend(); – Craig McKeachie May 16 '14 at 21:29