ember-rails hands-on intro

Matt Gauger

Mad Railers 2013-05-20

I work at Bendyworks

Bendyworks logo

Stephen, my boss here at Bendyworks, asked me to give this talk after I gave a brownbag technical talk on Ember-rails and how I'd used it for the Snow Mobile Raffle app. I want to show you how easy it is to include Ember-rails into your Rails app, and to use the default generators to start building your Ember app. And I'll have some lessons learned at the end.

Disclaimer:

I spend most of my time writing Backbone code that talks to Ruby services right now

Quite a few of us on the Bendyworks team have been writing Backbone since late last year on a big project for a client, and so I'm most familiar with Backbone. I have a lot of good things to say about Backbone, and a lot of hope for Ember. I don't always have good thing sto say about either Ember or Backbone, though.

What is Ember.js?

A framework for JS MVC apps

So Ember.js is a framework for JS MVC apps Or, another way of architecting these fancy websites we keep trying to build - We're building more complicated apps. - More work is being done on the clientside. - We're integrating with more external APIs where we don't control the server. - It's cool!

Emberjs.com website

If you're curious, you can go hit up the ember.js website. Their guides have gotten much better and their documentation for functions and classes is better now than it used to be, too.

Why Ember.js?

Why do we need another JS MVC framework? One size does not fit all. Ember has some unique features that take the burden of uninteresting problems off the developer. For example, Ember binds elements that change to DOM elements and updates them for you -- you don't have to call `render` like in other frameworks. I'll talk more about this later.

MVC => Model, View, Controller

So what does this really mean for a JS app? This is going to be for a JavaScript MVC app, which is a little different than what Rails considers MVC.

MVC => Model, View, Controller

(Let's not get in a debate as to whether it's really MVC when we say JS MVC, ok?)

Templates

Strings that we will render with data to present the user interface

(Note: not in the acroynm)

In Rails, this is what we call the View.. notice how we never write a View class in Rails? You could, but you don't have to.

View classes

Translates browser events to application events

Binds data to a template

Controller classes

Stores representations of application state

ie, a collection of model instances that came back from our API

Model classes

Stores persistant state

Typically loaded and saved to a server, but doesn't have to be

Router and route classes

Manages application state

Most importantly, handles URLs and sends messages the correct Controller for what is being requested

How does Ember.js compare to other frameworks?

Favors convention-over-configuration

Like Rails!

Opinionated about what your API should look like

This is the volatile ember-data project; now a part of Ember.js itself

Other frameworks let you define the API and how you talk to it. But that's at the expense of developer time -- now you have to spend time maintaining your mapping to your API in addition to the business logic!

Ember handles rendering and re-rendering DOM elements that are bound to data

Other frameworks leave calling render up to you

As a result, this means that Ember performs best when it takes over the entire viewport. This is unlike other frameworks in that you can't just use the framework for part of your page. It wants to be the whole app.

Push state (history), URLs are handled by Ember by default

Other frameworks let you turn this on

Ember.js is a whole framework

Other frameworks (like Backbone) are more like LEGO blocks

You can combine those frameworks in many ways

Ember is a set of reasonable defaults

Our example project:

A guest book

Because Discourse is a forum system on Rails and Ember, and we want to party like it's 1999!

dancing baby

A quick refresher

On the parts of Rails we'll be using

Rails resource generators:

Gives us:

Routes:

app/models/entry.rb
app/controllers/entries_controller.rb

(no views!)

If we wanted views, we'd use `rails generate scaffold`

active_model_serializers

Calling rails generate resource entry as before gives us:

app/serializers/entry_serializer.rb:

- Gives us the JSON resource - works with teh same resource generator as `rails generate resource` before We can trust it to pass those attributes for now, without any additional logic

Introducing ember-rails

Works with the same rails generate resource entry command we used earlier.

active_model_serializers gives us the API expected by ember-data

From rails generate resource entry with ember-rails, we get:

application.js

Requires all our code and instantiates the Ember app.

guest_book_app.js

Our application code, in turn, requires all of the Ember application classes:

store.js:

Keeps track of the ember-data API version we're on

Since `ember-data` has traditionally been in flux, they felt it was important to specify it in a file.

router.js:

(by default)

router.js with changes:

Create and view guest book entries in addition to an index

/routes/entries_routes.js:

Assuming we were a request for /entries, we go down into the index route now. This "find all" call on the model might get done by default now, but I wanted to point out that this is what calls our Rails resource to get the data.

/controllers/entries_controller.js:

Note that we're extending the ArrayController here since we handle a collection of model instances. By default, there's not a whole lot here.

/models/entry.js:

A couple things to note here: - We have to define all our attributes that we're getting from the API. - We're subclassing the DataStore classes now, instead of something from Ember. - This is a relic of ember-data being a different project. ```

/views/entries_view.js:

Again, not a lot going on here because we're using the basic functionality and "magic"

Let's look at a slightly more interesting View class

Handling browser events in the View:

Here we're sending the message of turnItUp to our controller with 11 as the data. In this way, we can wire up DOM controls to notify changes in the application state.

Our template for the application:

/templates/application.handlebars:

That's it! The outlet is where our app knows to create its views.

/templates/entries.handlebars:

this might be a little confusing. Why are we looping over Controller? Well, remember our EntriesController is an ArrayController, and it's gonna expose that list of entries to us.

Thanks! Questions?

I am:

twitter.com/mathiasx

github.com/mathias

This presentation lives at:

blog.mattgauger.com/madrailers-ember-rails/

My example raffle app lives at:

github.com/mathias/snow_mobile_raffle

#

/