47
Ember.js for Rails Developers Tech Talk - Feb. 21, 2014 Aaron Ortbals

Chaione Ember.js Training

Embed Size (px)

DESCRIPTION

Slides for a training given at Chaione on Ember.js from February 2014. https://github.com/aortbals/ember-github-example

Citation preview

Page 1: Chaione Ember.js Training

Ember.js for Rails Developers

Tech Talk - Feb. 21, 2014 Aaron Ortbals

Page 2: Chaione Ember.js Training

What we’ll be doing

• Building a Github Stat Tracker in Ember

• Work alone or in pairs

• Discuss various aspects of using Ember, Javascript, and their associated ecosystems along the way

Page 3: Chaione Ember.js Training

You’ll Need• Homebrew

• Git !

brew install git!

• Ruby !

brew install rbenv ruby-build!rbenv install 2.0.0-p353 # at least 1.9.3!rbenv rehash!gem update --system!gem install bundler rails!

• NPM, bower !brew install node!npm install -g bower!

• Clone the repo !

git clone https://github.com/aortbals/ember-github-example!bundle install

Page 4: Chaione Ember.js Training

Build Tools• A build system:

• compiles your assets

• prepares them for deployment

• serves them in development

• Caring about tooling is important

Page 5: Chaione Ember.js Training

Comparing Toolsets• ember-rails (what we are using)!

• rake, sprockets, internal REST API, rubygems

• ember-app-kit!

• JS, grunt, npm, bower, ES6 modules

• ember-appkit-rails!

• ember app kit conventions, sprockets, rubygems

Page 6: Chaione Ember.js Training

Future Build Tools• Broccoli is a build system meant to alleviate many

of the issues with grunt (and others)

• Goal of building in < 200ms

• O(1) build time as the app gets bigger

• Ember will likely standardize on this in the core library

• Easy transition from Ember App Kit

Page 7: Chaione Ember.js Training

What's in the repo • I've built a basic Rails 4 API that we can use to

consume Github

• Turbolinks is removed

• Provides a REST API, rake, build system (sprockets), little else

• Gives us more time to focus on Ember

Page 8: Chaione Ember.js Training

What’s in the repo• SCSS

• Bourbon: SCSS mixins

• Bourbon Neat: semantic grid

• Bitters: predefined typography, lists, etc

• A basic layout

• We will be building some components on top of the basic layout

Page 9: Chaione Ember.js Training

How we’ll work• Checkout a tag and make a practice branch

!git checkout v0.1!git checkout -b practice!

• Follow along, look for a when we hit a new tag

• We can go back to master and jump to a different step. Stash your changes, commit them, or throw them away

!git reset HEAD --hard!# or `git stash save "my progress"`!# or `git commit`!git checkout master!git checkout v0.2

v0.1

Tip: List tags!!

git tag -n!! v0.1 Getting started! v0.2 Step 2

Page 10: Chaione Ember.js Training

Ember Rails, Releases• Gemfile!

...gem 'ember-rails'gem 'ember-source', '~> 1.4.0'gem 'ember-data-source', '~> 1.0.0.beta.6’...

!

• Check http://emberjs.com/builds for the latest releases

• Ember has been very stable since 1.0; no breaking changes

• Adopted Chrome-style release cycle with semantic versioning

Page 11: Chaione Ember.js Training

Generating Ember Scaffolding

• Let's start by using ember-rails to generate our directory structure

!rails generate ember:bootstrap!

• Ember App Kit (and EAK-rails) promote JS to the top level - no more nested app/assets/javascripts/

v0.1

Page 12: Chaione Ember.js Training

Namespaced API• Let's setup our Rails API and configure Ember !

EmberGithubExample::Application.routes.draw do! get 'app/index'! root to: 'app#index'!! namespace :api do! # resources :users! # ...! end!! # Match all remaining paths and direct to Ember! get '*path' => 'app#index'! ...

v0.2

Page 13: Chaione Ember.js Training

One view, one controller

• app/controllers/app_controller.rb!

class AppController < ApplicationController! def index! end!end!

• touch app/views/app/index.html

Page 14: Chaione Ember.js Training

Setup our rails application template

• Bundle all templates together thanks to Sprockets

• views/layouts/application.html.erb!

<!DOCTYPE html>!<html>!<head>! <title>EmberGithubExample</title>! <%= stylesheet_link_tag "application", media: "all" %>! <%= javascript_include_tag "application" %>! <%= javascript_include_tag "templates/all" %>! <%= csrf_meta_tags %>!</head>!<body>!!<%= yield %>!!</body>!</html>!

• app/assets/javascripts/template/all.js !

//= require_tree .

v0.2

Page 15: Chaione Ember.js Training

Configure Ember's namespace

• store.js!EmberGithubExample.ApplicationAdapter = DS.ActiveModelAdapter.extend! namespace: 'api'!!EmberGithubExample.Store = DS.Store.extend! # Our custom adapter extends `DS.ActiveModelAdapter`! # with a namespace for our API! adapter: 'EmberGithubExample.ApplicationAdapter'

v0.2

Page 16: Chaione Ember.js Training

Setup the Ember app

• application.js.coffee - better logging in dev !window.EmberGithubExample = Ember.Application.create({! LOG_TRANSITIONS: true,! LOG_ACTIVE_GENERATION: true,! LOG_VIEW_LOOKUPS: true!})!

• Sprockets and Rails take care of compiling your app - makes it very easy to get started

v0.2

Page 17: Chaione Ember.js Training

Let's hello world!

• Ember will render the default application.hbs !<header>Welcome to the Github Stat Tracker!</header>!<section class="app">!</section>!<footer></footer>

v0.2

Page 18: Chaione Ember.js Training

Using Bower with Rails• Bower is a client-side package manager

• Don't vendor stuff. Just don't.

• .bowerrc!

{! "directory": "vendor/assets/components"!}!

• bower.json!{! "name": "ember-github-example",! "dependencies": {! "ember-data-extensions": "~1.0.0-beta.7"! }!}!

*I blogged about this

v0.2

Page 19: Chaione Ember.js Training

Ember Data• Makes it easy to retrieve records from the server

• Abstracts away the request/response cycle with a robust data model

• Provides an ORM-like experience

• Works well with Rails

• Ember Data is a stable beta

v0.2

Page 20: Chaione Ember.js Training

Talking with Github

• We have a basic REST API to query events for an organization

!localhost:3000/api/events?org=chaione!

• See https://developer.github.com/v3/activity/events/

v0.2

Page 21: Chaione Ember.js Training

Models• A model looks like this: !

App.User = DS.Model.extend!  firstName:  DS.attr('string')!  lastName:   DS.attr('string')!  email:      DS.attr('string')!  username:   DS.attr('string')! company:   DS.belongsTo('company')! createdAt: DS.attr('date')!

• Find a user: !user = App.User.find({ name: "Aaron" })!

• belongsTo == hasOne

v0.2

Page 22: Chaione Ember.js Training

Building some models

• Repo

• Actor

• Org

• Event - Go!

[ { "type": "Event", "public": true, "payload": { }, "repo": { "id": 3, "name": "octocat/Hello-World", }, "actor": { "login": "octocat", "gravatar_id": "somehexcode", }, "org": { "id": 1, "login": "github", }, "created_at": "2011-09-06T17:26:27Z", "id": "12345" }]

v0.2

Page 23: Chaione Ember.js Training

EventEmberGithubExample.Event = DS.Model.extend! type: DS.attr('string')! public: DS.attr('string')! createdAt: DS.attr('date')! actor: DS.belongsTo('actor')! repo: DS.belongsTo('repo')! org: DS.belongsTo('org')!

• Models can have relationships

• hasMany is supported

v0.3

Page 24: Chaione Ember.js Training

The Adapter• Ember has what is called 'the adapter'

• The adapter is responsible for translating data from a REST API to models

• Important to understand when a REST API does not adhere to expected conventions or is not consistent

• Ember Rails sets our adapter to DS.ActiveModelAdapter which works out of the box with Rails + ActiveModelSerializers

v0.3

Page 25: Chaione Ember.js Training

Polymorphic Associations!App.Like = DS.Model.extend! user: DS.belongsTo('user')! likeable: DS.belongsTo('likeable', {polymorphic: true})!!!App.Likeable = DS.Model.extend! likes: DS.hasMany('like')!!!App.Album = App.Likeable.extend! likes: DS.hasMany('like')!!!App.User = DS.Model.extend! likes: DS.hasMany('like')

v0.3

Page 26: Chaione Ember.js Training

Router• Ember represents each of the possible states in your

application as a URL

!

!

• The user can use the back button

• Avoids losing state

• If you hit refresh and the state changes, then 😂

interacts event

v0.4

Page 27: Chaione Ember.js Training

Router Example!

• Static routes

!

• Resource routes

• Nested resources

App.Router.map (match) ->!  @route 'app', { path: '/'}!  @route 'login'!  @route 'signup'! !  @resource 'users', ->!    @route 'new'!    @resource 'user',!      path: ':user_id'! !  @resource 'albums', ->!    @route 'new'!  @resource 'album',!    path: '/album/:album_id'!

v0.4

Page 28: Chaione Ember.js Training

A route• Each route has a route handler

• It finds the model, hands it to the controller, and renders a template

!App.UsersRoute = Ember.Route.extend  model: ->    App.User.find() App.UsersNewRoute = Ember.Route.extend  model: ->    App.User.createRecord() App.SignupRoute = App.UsersNewRoute

v0.4

Page 29: Chaione Ember.js Training

Declare our route

• https://api.github.com/orgs/chaione/events !EmberGithubExample.Router.map ()->! @resource 'org', { path: '/orgs/:orgName' }, ->! @resource 'events'!!!# Use the browser history API!EmberGithubExample.Router.reopen! location: 'history'

v0.4

Page 30: Chaione Ember.js Training

Event Route

• A Route provides a model hook !EmberGithubExample.EventsRoute = Ember.Route.extend! model: (params) ->! orgName = @modelFor('org').orgName! return [] unless orgName # No results!! @store.find('event', { org: orgName })

Route: @resource 'org', { path: '/orgs/:orgName' }, ->! @resource 'events'!

v0.4

Page 31: Chaione Ember.js Training

Event Template• Ember uses Handlebars which wraps {{things}} in

curly braces !

<div class="main">! <div class="image"></div>! <div class="text">! <div class="title">{{type}} by {{actor.login}}</div>! <div class="sub-title">! <span class="point">{{createdAt}}</span>! <span class="point">{{repo.name}}</span>! </div>! </div>!</div>!

v0.4

Page 32: Chaione Ember.js Training

Events Template

• In the events template we loop over the route model

!<section class="results">! {{#each model}}! {{partial "event"}}! {{/each}}!</section>

v0.4

Page 33: Chaione Ember.js Training

Controllers handle actions

• Controllers handle actions on your current view

• form submissions, clicks, etc

• They can also decorate the model with computed properties

v0.4

Page 34: Chaione Ember.js Training

Events Controller

EmberGithubExample.ApplicationController = Ember.Controller.extend! queryField: null! actions:! search: ->! if @get('queryField')! @transitionTo('events', @get('queryField'))!!!EmberGithubExample.EventsController = EmberGithubExample.ApplicationController.extend({})!

v0.4

Page 35: Chaione Ember.js Training

What do we have so far?• Models - represent our data from the server

• Router - declared route for our URL

• Route - hand the results data to our controller and template

• Events Template - loop over the results

• Event Template - present the event data

v0.4

Page 36: Chaione Ember.js Training

Computed PropertiesApp.Person = Ember.Object.extend! firstName: null! lastName: null!! fullName: (->! "#{@get('firstName')} #{@get('lastName')}"! ).property('firstName', 'lastName')!!!aaron = App.Person.create! firstName: "Aaron"! lastName: "Ortbals"!!aaron.get('fullName') # Aaron Ortbals

v0.5

Page 37: Chaione Ember.js Training

Add the repo url

• Add a computed property for the repo url

• Modify the template to display the repo url

Go!

v0.5

Page 38: Chaione Ember.js Training

Template Helpers

• Build a helper when you want to present data in a specific way

!Ember.Handlebars.helper 'from-now', (date) ->! return unless date! moment(date).fromNow()!!!<span>{{from-now createdAt}}</span>!

v0.5

Page 39: Chaione Ember.js Training

Bower + Moment + Helper

• Use moment to write a handlebars helper that displays the relative time

Go!

v0.5

Page 40: Chaione Ember.js Training

Demo

• Let's take a look at what we have so far

v0.6

Page 41: Chaione Ember.js Training

Add the gravatar image

• Let's add it, shall we?

v0.6

Page 42: Chaione Ember.js Training

Components• Components combine:

!

!

!

• Use them to define reusable pieces of UI + behavior in your application

View (Events)

Controller (Actions)+

Page 43: Chaione Ember.js Training

x-spinner<section class="center">! {{x-spinner delay=300}}!</section>!!App.XSpinnerComponent = Ember.Component.extend({! lines : 12, // The number of lines to draw! ...!! inserted: function() {! this._showSpinner();! }.on('didInsertElement'),!! teardown: function() {! this.spinner.stop();! }.on('willDestroyElement'),!! _showSpinner: function() {! var target = this.get('element');! this.spinner = new Spinner({ ... });! this.spinner.spin(target);! },!});!!Ember.Handlebars.helper('x-spinner', App.XSpinnerComponent);

Page 44: Chaione Ember.js Training

Diving Deeper• Complex actions

• Components

• Events

• Animations

• Real-time APIs

• Authentication

Page 45: Chaione Ember.js Training

What's Coming for Ember?

• Ember Conf 2014

• HTMLbars

• Build tools and modules

• Query params to hit release

Page 46: Chaione Ember.js Training

Resources

• emberjs.com/guides should be your first stop

• Smashing Magazine: In-depth Into to Ember

• Ember Community Twitter List

• My Ember bookmarks

Page 47: Chaione Ember.js Training

Thanks!