Getting started with Ember Data and Rails

I’ve recently become smitten by ember.js.   As a new framework, however, there isn’t a lot of documentation yet around some of the supporting elements.  I had a bit of a struggle with getting Ember Data working against Rails and thought I would write up this walkthrough to help out other folks working through the same issues.

I’m going to skip the Rails setup.   I’m also going to assume that there is an existing scaffold for a resource named Posts with one field called title and that you’ve set up the basics of an ember application in your Rails app.

First, you need to add Ember Data to your app/javascripts/application.js file if you haven’t already:

//= require  ember
//= require  ember-data

Next, create the Ember Data store in your Ember app.js file (I place these at ~/app/assets/javascripts/ember in my ember.js projects):


App = Ember.Application.create();
window.App = App;

App.store = DS.Store.create({
 adapter: DS.RESTAdapter.create({ bulkCommit: false }),
 revision: 3
});

The adapter tells Ember Data that your endpoints are REST endpoints.   You can write an adapter for endpoints that work differently than the JSON endpoints automatically generated with Rails’ scaffolding but thankfully we don’t need to do that.   That said, there is one one caveat:  we need to return the JSON for our Post resource wrapped in a top level key of the name of the model.   This is the gotcha that stumped me for a few hours.   To do this, open up post_controller.rb in your Rails app and edit the index method to wrap the response in a top level element with the plural of your model:


# GET /posts
# GET /posts.json
def index
  @posts = Posts.all

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: { posts: @posts } }
  end
end

That completed, let’s build our post model.   Create a post.js file in your Ember models directory:


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

App.Post.reopenClass({
  url: 'post'
});

What this does is tell Ember Data that you have a model Post with one field “title” and that you can find the REST endpoint for the index of such models at “/posts”.   Ember Data automatically pluralizes the endpoint so notice that we provided the singular here.

Ok, we have our model.   On to the controller.   Create a postController.js in the Ember controllers directory:


App.postsController = Em.ArrayController.create({
  content: App.store.findAll(App.Post)
});

What this controller does is automatically load all of the posts at instantiation using the Ember Data store that we created previously.   Easy huh?

With the controller created, let’s create a view that uses it starting with the template.   Create template/posts/index.hjs and add the following  template to it.


<ul>
   {{#each post}}
      <li>{{title}}</li>
   {{/each}}
</ul>

This keeps it simple – it displays all the posts in a list.

Ok, so we have our template.   Let’s create the view that hooks the template up to data.

Create views/posts/indexView.js:


App.PostIndexView = Em.View.extend({
  templateName: 'ember/templates/posts/index',
  postBinding: 'App.postsController'
});

The view is responsible for defining the template to use and what data should be bound to it.   Here we are using the template we created earlier and also using Ember’s Binding suffix magic to specify that post should be bound to the content of the postsController that we wrote earlier.

Ok – we have all the Ember elements together so the last step we need to do is replace the Rails app/views/posts/index.html.erb boilerplate with:

<script type="text/x-handlebars">
  {{view App.PostIndexView}}
</script>

Then you should be able to do a refresh on http://localhost:3000/posts and see your posts rendered in all their client side framework glory!

One comment

  1. Jo

    Nice post! I’ve found that active_model_serializers works (increasingly) well together with Ember Data — it allows you to do stuff like sideloading/embedding associations.

Leave a comment