ReefPointsBlog
Don’t miss Wicked Good Ruby Conf in Boston this October 11 – 12, 2014!

Building an Ember app with RailsAPI - Part 1

Brian Cardarella

This article was last updated on May 28, 2013 and reflects the state of Ember (1.0.0-rc4) and the latest build of Ember Data (0.13) as of that date.

Fork the project on Github!

Use the app live on Heroku

Lately I've been playing with Ember.js and I have really grown to love it. I get the same "AHA!" feeling I got building my first Rails app 7 years ago. Let's see how to build a simple CRUD app using the RailsAPI as the backend. We're going to build a new app and deploy to Heroku.

Part 1 - Getting Set Up

1
2
3
gem install rails-api
rails-api new ember-app
cd ember-app

Similar to the rails command RailsAPI comes with a rails-api command which under the hood is just using the normal rails CLI code but overriding some of the templates generated. Out of the box RailsAPI won't generate the asset pipeline directories as there is still some debate if it will use Sprockets, Rake-Pipeline or some other solution. In this example we're going to use Sprockets as it will save us a lot of time. RailsAPI is bundled with ActionPack which has Sprockets as a dependency. All we need to do is add in the directories

1
2
mkdir -p app/assets/{javascripts,stylesheets,images}
mkdir -p vendor/assets/{javascripts,stylesheets,images}

Now we need to copy in the vendored asset files. You can either build yourself our run the following to copy directly from my Github project

1
2
3
4
5
6
cd vendor/assets/javascripts
wget https://raw.github.com/bcardarella/ember-railsapi/master/vendor/assets/javascripts/ember-data.js
wget https://raw.github.com/bcardarella/ember-railsapi/master/vendor/assets/javascripts/ember.js
wget https://raw.github.com/bcardarella/ember-railsapi/master/vendor/assets/javascripts/jquery.js
wget https://raw.github.com/bcardarella/ember-railsapi/master/vendor/assets/javascripts/modernizr.js
cd ../../..

Note that if you're a Mac user, just replace wget (the Linux command) with curl -O (the Unix command) on the above lines.

Let's setup the directory structure for our Ember app

1
mkdir -p app/assets/javascripts/{controllers,models,views,templates}

And now we'll setup the load order in our app/assets/javascripts/application.coffee file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#= require modernizr
#= require jquery
#= require handlebars
#= require ember
#= require ember-data
#= require bootstrap
#= require_self
#= require store
#= require routes
#= require_tree ./controllers
#= require_tree ./models
#= require_tree ./templates
#= require_tree ./views

window.App = Ember.Application.create()

Add the routes.coffee and store.coffee files:

1
2
touch app/assets/javascripts/routes.coffee
touch app/assets/javascripts/store.coffee

And the app/assets/stylesheets/application.sass file

1
2
3
4
@import 'bootstrap'

body
  padding-top: 60px

That was a good amount of setup. Now we have the application structure for an Ember app in our asset pipeline. This will make things cleaner once we start coding.

Let's setup the necessary gem dependencies in our Gemfile. Just replace the entire contents with the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
source 'https://rubygems.org'

ruby '2.0.0'

gem 'rails', '3.2.13'
gem 'rails-api'
gem 'thin'
gem 'active_model_serializers', :github => 'rails-api/active_model_serializers'

group :development, :test do
  gem 'debugger'
  gem 'sqlite3'
end

group :production do
  gem 'pg'
end

group :assets do
  gem 'sass-rails', '~> 3.2'
  gem 'coffee-rails', '~> 3.2'
  gem 'compass-rails'
  gem 'uglifier'
  gem 'bootstrap-sass', '~> 2.0.3.0'
  gem 'handlebars_assets', '0.12.3'
end

group :development do
  gem 'quiet_assets'
end

There are two gems to take note of:

After this, don't forget to run bundle install from the command line to pick up the gems we just added.

Let's create a simple model and the serializer

1
2
rails-api g model User first_name:string last_name:string quote:text
rails-api g serializer User

Run 'rake db:migrate' to run the migration for our User model. Now open up app/serializers/user_serializer.rb and add the fields that require serialization

1
2
3
class UserSerializer < ActiveModel::Serializer
  attributes :id, :first_name, :last_name, :quote
end

Again, this will instruct Rails to turn our ActiveRecord object into a JSON object properly normalized for Ember.

Let's write the Controller. Create and edit app/controllers/users_controller.rb

1
2
3
4
5
class UsersController < ApplicationController
  def index
    render json: User.all
  end
end

Take note that we are inheriting ApplicationController but in a RailsAPI app ApplicationController itself inherits from ActionController::API instead of ActionController::Base.

This basic controller will serve up all of our users to our Ember app. We'll add more later.

Now let's add some routes to config/routes.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
EmberApp::Application.routes.draw do
  class FormatTest
    attr_accessor :mime_type

    def initialize(format)
      @mime_type = Mime::Type.lookup_by_extension(format)
    end

    def matches?(request)
      request.format == mime_type
    end
  end

  resources :users, :except => :edit, :constraints => FormatTest.new(:json)
  get '*foo', :to => 'ember#index', :constraints => FormatTest.new(:html)
  get '/', :to => 'ember#index', :constraints => FormatTest.new(:html)
end

A few things are happening here:

So let's create that Ember controller. This will act as the primary application serving controller that is hit when people visit the app. Create and edit app/controllers/ember_controller.rb

1
class EmberController < ActionController::Base; end

Note that we are inheriting from ActionController::Base this time and not ApplicationController. This is so that the controller actions can respond to non JSON requests.

Now we will add the view in app/views/ember/index.html.erb

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang='en'>
  <head>
    <%= stylesheet_link_tag :application, :media => :all %>
    <%= javascript_include_tag :application %>
    <title>Title</title>
  </head>
  <body>
  </body>
</html>

That is all the view that your Ember app will need. Ember will automatically attach its own default template to the <body> tag.

Let's add some data to db/seeds.rb

1
2
User.create(:first_name => 'William', :last_name => 'Harrison', :quote => "I'm just singin' in the rain!")
User.create(:first_name => 'Abraham', :last_name => 'Lincoln', :quote => "I'd like to see a show tonight.")

Now run your migrations and seed

1
rake db:migrate db:seed

Ok, now our app is in a good spot to start developing an Ember app with. Let's review what we did

  1. Generated a new app using rails-api
  2. Set up the javascript and stylesheet assets
  3. Wrote a very simple JSON API for returning all users

In Part 2 we'll build the Ember app itself.