Extroverted Introspection

Me looking at new things

Ember Data: Nested Resources

As anyone who has worked with Ember.js before can tell you, its learning curve is as steep as the framework is awesome. And its awesome indeed. That is why I want to share my insights from this afternoon to provide some instructions on how to use Ember Data with nested resources.

For this example, I will use the ubiquitous Blog application where each Post has many Comments. As such, the URLs provided by the REST interface will look like this:

  • /posts provides all posts
  • /posts/:id(.:format) provides access to a single post
  • /posts/:id/comments returns all the comments
  • /posts/:id/comments/:id shows only the data for a specific comment

The Ember model will probably look familiar to you, but I’ll include it here for the sake of completeness:

model.coffee
1
2
3
4
5
6
7
8
9
App.Post = DS.Model.extend
  title: DS.attr('string')
  # ...some more attributes here...
  comments: DS.hasMany('comment', { async: true })

App.Comment = DS.Model.extend
  title: DS.attr('string')
  # ...some more attributes here...
  post: DS.belongsTo('post', { async: true })

Right now, without any further configuration, Ember Data would try to access comments via the URLs /comments or /comments/:id. So how do we tell it to use the nested URLs instead?

The answer is surprisingly simple and hidden in the findHasMany documentation of the RESTAdapter class.

Effectively, all you need to do is to provide a links attribute in your JSON which contains a map of associated model attributes and their corresponding REST URL. In our case it happens to look exactly like the one from the Ember documentation:

GETlink
1
2
3
4
5
6
7
{
  "post": {
    "id": 1,
    "title": "Rails is omakase",
    "links": { "comments": "/posts/1/comments" }
  }
}

As a bonus, here’s some sample template code for a Jbuilder-based application:

_post.json.jbuilder
1
2
3
4
5
json.id post.id
json.title post.title
json.links do
  json.comments "/posts/#{post.id}/comments"
end
show.json.jbuilder
1
2
3
json.post do
  json.partial! 'post', post: @post
end
index.json.jbuilder
1
json.posts @posts, partial: 'post', as: :post