Setting up a Rails 5 API + Ember project

This is a simple tutorial for setting up a new Rails JSON API + Ember.js project with ember-cli-rails and deploying to Heroku.

At the time of writing Rails 5 has not been released yet, but is coming soon. Hopefully some steps mentioned in this post, will not be needed, once Rails 5 has been released.

Prerequisites

  • Ruby 2.3.0
  • PostgreSQL
  • Node.js
  • npm
  • Git
  • Heroku toolbelt
  • A Heroku account

Setting up Rails

First you'll need the latest version of Rails installed:

gem install --pre rails  

When Rails has been installed you can create a new project like this:

rails new myproject --api --edge --database=postgresql  

To explain the additional arguments - --api will make Rails generate an API-only project, --edge will make the project use the latest Rails and --database=postgresql will change the database dependency and adapter to PostgreSQL, instead of SQLite.

Setting up Ember CLI

Ember CLI is a really nice tool, heavily inspired by Rails, that helps you setting up your Ember project and generating boilerplate. As it states on the web page, install it by command:

npm install -g ember-cli  

When it's been installed, you should change directory to your new Rails project myproject and create a new Ember project:

ember new frontend --skip-git  

The parameter --skip-git is important, as we will use the Rails project root as Git repository root.

Now we have a new Rails API project and an Ember project. Time to put the pieces together.

Setting up ember-cli-rails

ember-cli-rails is as the time of writing not supporting Rails 5, but there is a branch where some issues have been fixed. Add the following line to your Gemfile.

gem 'ember-cli-rails', github: 'thoughtbot/ember-cli-rails', branch: 'sd-rails-5'  

Update dependencies:

bundle  

I found that even when using the sd-rails-5 branch, the API-only Rails mode will not work without changing ApplicationController to extend from ActionController::Base (default for normal Rails projects) instead of ActionController::API. That is, the first line of app/controllers/application_controller.rb should be:

class ApplicationController < ActionController::Base  

Serving the Ember app through Rails

Create the Ember CLI initializer.

rails generate ember:init  

Add the Ember app to routes.rb by adding the following line:

mount_ember_app :frontend, to: "/"  

Finally, install your Ember application's dependencies:

rake ember:install  

Now you may try boot Rails and the Ember app:

rails s  

If you now access http://localhost:3000 you should see the Welcome to Ember welcome message. It might take a few seconds to load the page, as the Ember app will be automatically rebuilt when needed.

Produce and consume JSON API

Up to this point, all you have achieved is that you have an Ember app and a server to serve it, and there is not really any use for Rails. Let's make real use of Rails!

In order to fetch data from your Rails backend from Ember with Ember Date (without creating your own custom adapter), you need to make sure Rails is rendering JSON according to the JSON API spec.

Rails

You will need to make two changes to Rails. Add the latest release of active_model_serializers to your Gemfile:

gem 'active_model_serializers', '~> 0.10.0.rc4'  

When active_model_serializers has been added, serializers will be added when generating new scaffolds with rails g scaffold. In the serializer you can specify which fields to include and do custom serialization of certain fields. It could for example look like this:

class UserSerializer < ActiveModel::Serializer  
  attributes :id, :username, :email
end  

Next step is to create the file config/initializers/active_model_serializer.rb with the following content:

ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::JsonApi  

It is also a good idea to gather all API routes in some common place, to separate them from the Ember routes. In order to do this, create a new scope in the bottom of routes.rb.

scope '/api/v1' do  
  # define your resources and routes here
end  

Now Rails should produce JSON API. It's time consume it from Ember.

Ember

We need to create a custom adapter for the whole Ember app. Create the file frontend/app/adapters/application.js with the following content:

import DS from 'ember-data';

export default DS.JSONAPIAdapter.extend({  
  namespace: 'api/v1',

  pathForType: function(type) {
    let underscored = Ember.String.underscore(type);
    return Ember.String.pluralize(underscored);
  }
});

This adapter will tell Ember that we want a JSONAPIAdapter that will request resources in /api/v1/<route>. It also makes sure that models in kebab-case are are requested in snake_case, as that is preferred in Rails.

We also need a custom serializer. In order to use snake_case also for the JSON API requests and responses, create frontend/app/serializers with the following content:

import DS from 'ember-data';

var underscore = Ember.String.underscore;

export default DS.JSONAPISerializer.extend({  
  keyForAttribute: function(attr) {
    return Ember.String.underscore(attr);
  },
  keyForRelationship: function(key) {
    return Ember.String.underscore(key);
  }
});

Restart Rails (not normally needed during development) and you'll be ready to start implementing your awesome web page!

Deploying to Heroku

If you want to go public or share your web page with your friends, Heroku is a good choice - easy to get started and free.

Before you can deploy to Heroku, you must add all files to Git.

git ci -am 'rails edge + ember-cli-rails project'  

If you haven't been using Heroku toolbelt before you must login to use it:

heroku login  

Then you can create and setup the Heroku app with the following commands. For more details, see ember-cli-rails and Getting Started with Rails 4.x on Heroku.

heroku create  
heroku buildpacks:clear  
heroku buildpacks:add --index 1 heroku/nodejs  
heroku buildpacks:add --index 2 heroku/ruby  
heroku config:set NPM_CONFIG_PRODUCTION=false  
heroku config:unset SKIP_EMBER  

Now everything is ready for deploy.

git push heroku master  

When your app has been deployed, open it in a browser by typing:

heroku open  

If everything has worked, you should now, once more, be greeted by Ember's welcome message.

I hoped you enjoyed this tutorial. Good luck with your new Rails 5 API + Ember web page!