---
title: EmberJS with a Separate Rails API
teaser: |
  What we learning writing an Ember.js app as a separate codebase,
  deployed separately from the backend Ruby on Rails API.
  Testing was particularly hard!
tags: web,ember,javascript
author: Jason Draper
published_on: 2014-02-25
---

We just wrapped up a large client project using [EmberJS] and we learned a few
things that are interesting to share.

Ember made this project easier. There are times that a JavaScript framework is
unnecessary and there are times that it makes the code much cleaner. This was
the latter.

# Split Development

We built our <abbr title="Application Programming Interface">API</abbr> and our
JavaScript application as two completely separate applications. We had one repo
that held a very basic Rails application with Ember on top and another repo that
held the <abbr title="Application Programming Interface">API</abbr> built in
Rails.

## Rails instead of Yeoman, Grunt, Brunch, etc

There are a lot of front end development tools that will allow you to build an
EmberJS application using CoffeeScript, Sass and the other tools that we like to
use on projects. After evaluating them we settled on using a basic Rails
application instead; primarily for simplicity. The project had a short timeline
and we didn't want to have to worry about another tool that we were not familiar
with. In the future I would love to try building an Ember UI using a front end
tool such as [Tapas with Ember] but we didn't have any complaints with using
Rails in this case and it made our stack a bit simpler to use.

For Ember in our Rails app we used the [ember-rails] gem. It provides a
basic folder structure for your Ember application inside the
`app/assets/javascripts` directory. The directory structure is similar to a
Rails application as you can see below.

    controllers/
    helpers/
    components/
    models/
    routes/
    templates/
    templates/components
    views/

The one thing that is strange when using the gem for a UI only application is
that your `app/` directory in Rails is basically unused except for the
`app/assets/javascripts/` where all the actual work will happen.  Another
project, [EmberAppkitRails], solves this issue by putting the `app/` directory
into asset pipeline. This is an interesting idea. The gem is pre-1.0 so the
<abbr title="Application Programming Interface">API</abbr> could change.

Ember-rails also provides configuration variables for using the development or
production version of Ember depending on your current enviroment. This is nice
so that your Ember debug information is automatically removed in production.

## Fixtures in Development

To allow rapid development, we built the UI in Ember using only fixtures in
[Ember Data]. This allowed us to very quickly build out complex interactions
without having to worry about the <abbr title="Application Programming
Interface">API</abbr> being in place. This was a huge help in moving fast and
later we backfilled the API. Being able to change property names without having
to worry about migrations or outside <abbr title="Application Programming
Interface">API</abbr> changes was very efficient. An Ember Data fixture is a
simple <abbr title="JavaScript Object Notation">JSON</abbr> object and you can
quickly modify it to your needs. It also handles has many and belongs to
references using the IDs of other elements.

```javascript
App.User.FIXTURES = [
  {
    id: 1
    email: 'user@example.com'
    posts: [1, 3]
  }
  {
    id: 2
    email: 'secondUser@example.com'
    posts: [2,4]
  }
]

App.Post.Fixtures = [
  {
    id: 1
    title: 'The Art of Vim'
    user: 1
  }
  {
    id: 2
    title: '15 Minute Blog in EmberJS'
    user: 2
  }
]
```

There are downsides to this approach. The first one is the backfill process. We
waited too long in the project to connect our <abbr title="Application
Programming Interface">API</abbr> to Ember and ran into issues.

The other problem is that by having the applications in two seperate repos, you
can't easily have a full integration test. In order to do this you would need to
run both applications on the same machine simultaneously. You would also need
some way to make sure that both of the applications were on the same revision
for the test.

We decided to test the apps seperately and trust that the <abbr
title="Application Programming Interface">API</abbr> is what we've said it was.
This can be frustrating but in our case, it didn't turn out to be a real
problem. Once you have wired your <abbr title="Application Programming
Interface">API</abbr> to the UI, you should never change your UI without also
changing the API. This was enforced in code review only.

## CoffeeScript

I love CoffeeScript and as a company we have embraced it for our all our
projects.  Ember is no exception to that. CoffeeScript made our Ember
application more readable and easier to work with objects. The only thing that
is odd is the syntax for a [computed property], but that is a minor issue and we
quickly adjusted to seeing it as normal.

```coffeescript
fullName: (->
  "#{@get('firstName')} #{@get('lastName')}"
).property('firstName', 'lastName')
```

## Fast Tests

By removing the <abbr title="Application Programming Interface">API</abbr> from
the UI application, we were able to write feature specs entirely in
CoffeeScript. This was a huge benefit to the overall success of the project. We
could test every interaction in our app precisely and not have to worry about
the normal overhead associated with those types of feature specs. The specs only
had to deal with JavaScript so it was really fast. A full `rake` for our UI
application was 32.770 seconds including starting the Rails environment. The
suite had a total of 71 examples, most of which were feature specs.

# Testing in General

We found Ember to be very easy to test in general. Most things break down to
`Ember.Object` and it was easy to grab a controller in a test and verify that a
property works as expected. Because we wanted to use [Mocha] with [Chai BDD
matchers] instead of [QUnit], the initial test setup was a bit complex but
after using [Konacha] with a [Mocha adapter], it was smooth sailing. The
extra setup time for Mocha over QUnit was definitely worth it. The syntax has a
much more readable format.

```coffeescript
describe 'AggregateStatsController', ->
  describe 'summed properties', ->
    beforeEach ->
      stats = []
      stats.push Ember.Object.create
        clicks: 2
        cost: 1.99
      stats.push Ember.Object.create
        clicks: 4
        cost: 2.00

      model = Ember.Object.create(dailyStats: stats)

      controller = App.__container__.lookup('controller:aggregate_stat')
      controller.set('model', model)

    it 'will sum the number of clicks in the model', ->
      expect(controller.get('clicks')).to.equal(6)

    it 'will sum the cost in the model', ->
      expect(controller.get('cost')).to.equal(3.99)
```

Feature specs were also very easy to handle. Ember has built in [integration
test helpers] that worked for most of our needs and we used jQuery to augment
them in our expectations. The specs were fast enough that we could test small
details in the interface that we might otherwise want to omit. Being able to
test all the UI interactions gave us a lot of faith in our codebase.

```coffeescript
describe 'Navigating SEM Campaigns', ->
  before ->
    App.DailyStat.FIXTURES = [
      {
        id: 1
        clicks: 11
      }
      {
        id: 2
        clicks: 10
      }
    ]

    App.SemCampaign.FIXTURES = [
      {
        id: 1
        name: 'Opening Campaign'
        status: 'active'
        dailystats: [1]
      }
      {
        id: 2
        name: 'Final Sale'
        status: 'active'
        dailyStats: [2]
      }
    ]

    it 'shows the daily stats information for campaign', ->
      visit('/').then ->
        clickLink('SEM Campaigns').then ->
          expect(pageTitleText()).to.equal('SEM Campaigns')
          expect(pageHasCampaignWithTitle('Opening Campaign')).to.be.true
          expect(statusFor('Opening Campaign')).to.equal('icon-active')
          expect(clicksFor('Opening Campaign')).to.equal('11')
          expect(pageHasCampaignWithTitle('Final Sale')).to.be.true
```

## Naming your tests

Konacha and [Teaspoon] both have the downside of not showing a filename when a
spec fails. This caused us a lot of pain when we first started so we decided on
the convention of using the first `describe` docstring as the name of the file.
In the case above our file would be named
`navigating_sem_campaigns_spec.js.coffee`. This worked out great and made it
much easier to find a failing spec.

# Overall

Ember is far stabler than I would have imagined given that 1.0 was just released
6 months ago. If you have a project that is highly interactive and requires a
lot of data binding, I recommend trying it out. The Ember community has been
incredibly helpful on [Stack Overflow], their [forums] and their [IRC
channel].

[EmberJS]: http://emberjs.com/
[Ember Data]: https://github.com/emberjs/data
[Mocha]: https://mochajs.org/
[Chai BDD matchers]: http://chaijs.com/api/bdd/
[QUnit]: https://qunitjs.com/
[Konacha]: https://github.com/jfirebaugh/konacha
[Mocha adapter]: https://github.com/teddyzeenny/ember-mocha-adapter
[Stack Overflow]: http://stackoverflow.com/tags/ember.js/
[forums]: http://discuss.emberjs.com/
[IRC channel]: http://emberjs.com/community/
[Tapas with Ember]: https://github.com/mutewinter/tapas-with-ember
[ember-rails]: https://github.com/emberjs/ember-rails
[EmberAppkitRails]: https://github.com/dockyard/ember-appkit-rails
[integration test helpers]: http://emberjs.com/guides/testing/integration/
[Teaspoon]: https://github.com/modeset/teaspoon
[computed property]: https://thoughtbot.com/blog/custom-ember-computed-properties
