From Ember-Rails to Ember CLI

Blake Williams

The majority of Ember applications I’ve worked on have been powered by the Ember-Rails gem. Ember-Rails is great but can make your Ember app feel like a second class citizen when it’s just as important as the Rails API that powers it.

Ember CLI solves this issue by separating your Ember application from Rails and providing an environment to develop, build, and test your Ember applications.

From globals to modules

The biggest change when migrating to Ember CLI was moving away from a global App namespace to ES6 modules. With Ember-Rails app.coffee would look like this:

window.App = Ember.Application.create
  rootElement: "#ember_app_container"

Ember CLI uses ES6 modules to import dependencies and export functions and objects:

`import Ember from "ember";`

App = Ember.Application.extend
  rootElement: "#ember-app-container"

`export default App;`

Unfortunately CoffeeScript doesn’t support ES6 module syntax yet, so we have to embed JavaScript directly using backticks to import and export modules.

Instead of creating our App instance directly we export it and Ember CLI will instantiate it for us. If we were using JavaScript instead of CoffeeScript we could export it directly instead of having to assign it to a variable:

import Ember from "ember";

export default Ember.Application.extend({
  rootElement: "#ember-app-container"
});

Ember CLI also comes with its own custom resolver that takes advantage of ES6 modules, giving us different filename conventions. Underscores are replaced with dashes, .js.coffee is replaced with just .coffee if you’re using CoffeeScript, and the “_type” suffix is removed entirely, e.g.: controllers/application_controller.js.coffee would become controllers/application.coffee.

These changes are necessary since ES6 modules use the relative path and filename to generate the module name. For example, controllers/application.coffee would export to a module named your-app-name/controllers/application.

Testing

Ember CLI ships with a test environment with QUnit as the default testing framework. When we converted from Ember-Rails we were using Mocha and were forced into adopting QUnit.

Fortunately QUnit-BDD allowed us to get away with minor changes to our test suite such as eq becoming equal and having to write our own include helper.

Now that Mocha is supported in Ember CLI through ember-cli-mocha we can skip QUnit/QUnit BDD entirely.

Deploying

After the migration was completed and the tests were passing we needed to figure out how to deploy it. We ended up going with Heroku and this Ember CLI buildpack that builds and serves our application for us.

We took advantage of Ember CLI’s config/environment.js file to point Ember-Data to different endpoints based on the environment the application is built/running in.

if environment == "staging"
  ENV.API_HOST = "https://api-staging.herokuapp.com"

if environment == "production"
  ENV.API_HOST = "https://api.herokuapp.com"

We import these values into app/adapters/application.coffee as config and set the adapters host property.

`import DS from "ember-data";`
`import config from "../config/environment";`

ApplicationAdapter = DS.ActiveModelAdapter.extend
  host: config.API_HOST

`export default ApplicationAdapter`

Now every time we use the adapter the host is set for us based on the environment.

Wrapping up

Ember CLI is still young and has a few bumps to smooth out but also has some advantages over other options with fast incremental builds, live reload support, and the ability to extend Ember and Ember-CLI through addons.

Best of all, Ember CLI allows us to separate our front-end from our API and makes Ember feel like a first class citizen instead of an afterthought.