Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Chaione Ember.js Training

1,156 views

Published on

Slides for a training given at Chaione on Ember.js from February 2014.

https://github.com/aortbals/ember-github-example

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Chaione Ember.js Training

  1. 1. Ember.js for Rails Developers Tech Talk - Feb. 21, 2014 Aaron Ortbals
  2. 2. 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
  3. 3. 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
  4. 4. Build Tools • A build system: • • prepares them for deployment • • compiles your assets serves them in development Caring about tooling is important
  5. 5. Comparing Toolsets • ember-rails (what we are using)! • • ember-app-kit! • • rake, sprockets, internal REST API, rubygems JS, grunt, npm, bower, ES6 modules ember-appkit-rails! • ember app kit conventions, sprockets, rubygems
  6. 6. 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
  7. 7. 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
  8. 8. 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
  9. 9. v0.1 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 Tip: List tags! ! git tag -n! ! v0.1 v0.2 Getting started! Step 2
  10. 10. 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
  11. 11. v0.1 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/
  12. 12. v0.2 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'! ...
  13. 13. One view, one controller • app/controllers/app_controller.rb ! class AppController < ApplicationController! def index! end! end! • touch app/views/app/index.html
  14. 14. v0.2 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 .
  15. 15. v0.2 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'
  16. 16. v0.2 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
  17. 17. v0.2 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>
  18. 18. v0.2 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
  19. 19. v0.2 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
  20. 20. v0.2 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/
  21. 21. v0.2 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
  22. 22. v0.2 Building some models [ { • Repo • Actor • Org • "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" Event - Go! } ]
  23. 23. v0.3 Event EmberGithubExample.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
  24. 24. v0.3 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
  25. 25. v0.3 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')
  26. 26. v0.4 Router • Ember represents each of the possible states in your application as a URL ! interacts event ! • The user can use the back button • Avoids losing state • If you hit refresh and the state changes, then 😂
  27. 27. v0.4 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'!
  28. 28. v0.4 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
  29. 29. v0.4 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'
  30. 30. v0.4 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'!
  31. 31. v0.4 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>!
  32. 32. v0.4 Events Template • In the events template we loop over the route model ! <section class="results">! {{#each model}}! {{partial "event"}}! {{/each}}! </section>
  33. 33. v0.4 Controllers handle actions • Controllers handle actions on your current view • • form submissions, clicks, etc They can also decorate the model with computed properties
  34. 34. v0.4 Events Controller EmberGithubExample.ApplicationController = Ember.Controller.extend! queryField: null! actions:! search: ->! if @get('queryField')! @transitionTo('events', @get('queryField'))! ! ! EmberGithubExample.EventsController = EmberGithubExample.ApplicationController.extend({})!
  35. 35. v0.4 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
  36. 36. v0.5 Computed Properties App.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
  37. 37. v0.5 Add the repo url • Add a computed property for the repo url • Modify the template to display the repo url Go!
  38. 38. v0.5 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>!
  39. 39. v0.5 Bower + Moment + Helper • Use moment to write a handlebars helper that displays the relative time Go!
  40. 40. v0.6 Demo • Let's take a look at what we have so far
  41. 41. v0.6 Add the gravatar image • Let's add it, shall we?
  42. 42. Components • Components combine: ! ! View (Events) + Controller (Actions) ! • Use them to define reusable pieces of UI + behavior in your application
  43. 43. 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);
  44. 44. Diving Deeper • Complex actions • Components • Events • Animations • Real-time APIs • Authentication
  45. 45. What's Coming for Ember? • Ember Conf 2014 • HTMLbars • Build tools and modules • Query params to hit release
  46. 46. Resources • emberjs.com/guides should be your first stop • Smashing Magazine: In-depth Into to Ember • Ember Community Twitter List • My Ember bookmarks
  47. 47. Thanks!

×