Chaione Ember.js Training
-
Upload
aortbals -
Category
Technology
-
view
733 -
download
0
description
Transcript of Chaione Ember.js Training
Ember.js for Rails Developers
Tech Talk - Feb. 21, 2014 Aaron Ortbals
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
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
Build Tools• A build system:
• compiles your assets
• prepares them for deployment
• serves them in development
• Caring about tooling is important
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
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
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
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
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
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
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
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
One view, one controller
• app/controllers/app_controller.rb!
class AppController < ApplicationController! def index! end!end!
• touch app/views/app/index.html
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Events Template
• In the events template we loop over the route model
!<section class="results">! {{#each model}}! {{partial "event"}}! {{/each}}!</section>
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
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({})!
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
v0.4
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
Add the repo url
• Add a computed property for the repo url
• Modify the template to display the repo url
Go!
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>!
v0.5
Bower + Moment + Helper
• Use moment to write a handlebars helper that displays the relative time
Go!
v0.5
Demo
• Let's take a look at what we have so far
v0.6
Add the gravatar image
• Let's add it, shall we?
v0.6
Components• Components combine:
!
!
!
• Use them to define reusable pieces of UI + behavior in your application
View (Events)
Controller (Actions)+
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);
Diving Deeper• Complex actions
• Components
• Events
• Animations
• Real-time APIs
• Authentication
What's Coming for Ember?
• Ember Conf 2014
• HTMLbars
• Build tools and modules
• Query params to hit release
Resources
• emberjs.com/guides should be your first stop
• Smashing Magazine: In-depth Into to Ember
• Ember Community Twitter List
• My Ember bookmarks
Thanks!