Zack Hubert

Ember.js and Rails, Part 1: Rails Setup

Today, I’d like to look at building an app with a Rails server-side implementation and an Ember.js client. The goal of this post is to get Ember and Rails integrated and a single resource fully wired up.

I’ve done some work in Backbone.js and Spine.js, but the Keynote by @wycats yesterday has motivated me to take a look at Ember, so let’s dig in.

First up the Rails side of the equation (Rails 3.2.3):

1
$ rails new ember-rails-demo

After the usual bundling and such, we want to install ActiveModelSerializers to make our creation of JSON a bit easier. You could just use jBuilder or .as_json hashes, but I think AMS will pay off in spades over the course of a large project so let’s use that here.

First add the following to the Gemfile:

1
gem "active_model_serializers", :git => "git://github.com/josevalim/active_model_serializers.git"

And rebundle…

1
$ bundle install

Now let’s make our single resource and a serializer:

1
2
$ rails g resource post title:string body:string
$ rails g serializer post title body id

And put the basics into our posts_controller:

app/controllers/posts_controller.rb
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class PostsController < ApplicationController
  def index
    @posts = Post.all

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

  def show
    @post = Post.find(params[:id])

    respond_to do |format|
      format.json { render json: @post }
    end
  end

  def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        format.json { render json: @post, status: :created, location: @post }
      else
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    @post = Post.find(params[:id])

    respond_to do |format|
      if @post.update_attributes(params[:post])
        format.json { render json: nil, status: :ok }
      else
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy

    respond_to do |format|
      format.json { render json: nil, status: :ok }
    end
  end
end

One cool thing about AMS is that expects to integrate with a scope for auth (this enables authorization of what attributes and associations are available via serialization), in most cases current_user so let’s install Sorcery to have something for it to work with. If I was building a real system, there would be more steps to take here, but it’s trivial and I don’t want to waste space on it.

In Gemfile:

1
gem 'sorcery'

And rebundle…

1
$ bundle install

Finally, run the install generator…

1
$ rails generate sorcery:install

And get our database up to speed…

1
2
$ rake db:create
$ rake db:migrate

Let’s put some dummy data into seeds.rb:

db/seeds.rb
1
2
Post.create(title: 'Hello', body: 'world')
Post.create(title: 'foo', body: 'bar')

Running the server and calling the API we see some serialized posts. Woot!

1
2
3
$ rails server
$ curl localhost:3000/posts.json # from another window
{"posts":[{"title":"Hello","body":"world"},{"title":"foo","body":"bar"}]}%

Some final cleanup…set default route in config/routes.rb:

1
2
3
4
EmberRailsDemo::Application.routes.draw do
  resources :posts
  root :to => 'posts#index'
end

And make an app/views/posts/index.html.erb (remove public/index.html)

1
<h1>Posts</h1>

Of course there will be more to do with this view, but at least the app can run cleanly at this point, so let’s stop here.

Comments