Mends.One

How do I make an Ember-Data has-many collection that is defined by another API endpoint?

Ember.js, Rest, Ember Data

I've got a model, Post that has many Comments. The response for GET /posts/12 is pretty Ember-Data-friendly:

{
  "post": {
    "id": 12,
    "title": "I Love Ramen",
    "created_at": "2011-08-19T14:22",
    "updated_at": "2011-08-19T14:22",
    "body": "..."
  }
}

The API for that Post's Comments, however, is GET /posts/12/comments, which returns

{
  "comments": [
    {
      "id": 673,
      "author_id": 48,
      "created_at": "2011-08-21T18:03",
      "body": "Me too!"
    }
  ]
}

What can I do to my model or my adapter to tell it that for Post 12's Comments, use /posts/12/comments? Notice that the Post itself has no knowledge of the Comment IDs.

Update

In response to buuda's answer, here are some clarifications:

The Post must be able to look up its Comments so that I can (a) show the comments on the PostRoute and (b) have properties on Post like

hasComments: function() {
  return this.get('comments.length') > 0;
}.property('comments')

It's fine with me if I have to implement the comments computed property, though. In the above-mentioned answer, buuda suggests

App.Comments.find({ id: postId });

How do I get the datastore to fetch /posts/:postId/comments instead of /comments?postId=:postId?

1
J
James A. Rosen
Jump to: Answer 1

Answers (1)

You don't need to setup any relationship between models, necessarily. The nested resources allow you to fetch the appropriate data. With this router:

App.Router.map(function() {
  this.resource('posts', { path: '/posts/:post_id' }, function() {
    this.route('edit');
    this.resource('comments', function() {
      this.route('new');
    });
  });
});

The CommentsRoute can get the model for the resource it is contained in and then fetch the comments with that post id:

App.CommentsRoute = Ember.Route.extend({
   model: function() {
       var post = this.modelFor('posts');
       var postId = post.get('id');
       return App.Comments.find({ id: postId });
   }
});

The posts model doesn't need to know the comment ids, but the underlying datastore has to return appropriate comments based on post id queries. That returned array is then used as the model for the comments route.

Edit:

I assume you are using ember-data. If so, nested resource URLs (posts/:postId/comments) are not yet supported. To show comments in the post route you might want to fetch the comments data, set it on a comments controller, use controller injection ('needs') in the posts controller, and use the experimental 'control' handlebars tag to show the comments view:

App.PostsRoute = Ember.Route.extend({
   setupControllers: function() {
       var post = this.modelFor('posts');
       var postId = post.get('id');
       var comments = App.Comments.find({ id: postId });
       this.controllerFor('comments').set('content', comments);
   }
});

I explain how to use the experimental control tag here: How to Render HasMany Associations With Their Own Controller

2
B
buuda

Comments:

James A. Rosen said:
Thanks for the quick response! I've added some clarification to my post to address some of your points.

Related Questions