Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ember & Rails - Convention over configuration on both sides of the tubes

Balint Erdi
October 03, 2013

Ember & Rails - Convention over configuration on both sides of the tubes

My presentation on Ember & Rails I gave at Arrrrcamp Belgium (http://arrrrcamp.be/), Ghent, 2013, October 3.

Balint Erdi

October 03, 2013
Tweet

More Decks by Balint Erdi

Other Decks in Technology

Transcript

  1. “(...) Seafarers in the tropics commonly brought home exotic fauna

    as souvenirs. Parrots were particularly popular because they were colorful, could be taught to speak, and were easier to care for than, say, monkeys.” Saturday, October 5, 13
  2. “(...) Seafarers in the tropics commonly brought home exotic fauna

    as souvenirs. Parrots were particularly popular because they were colorful, could be taught to speak, and were easier to care for than, say, monkeys.” (Read: they crapped everywhere but at least wouldn't throw it at you.) Saturday, October 5, 13
  3. “(...) However, one can't imagine a crewman actually heaving at

    the capstan with a bird perched on him.” http://www.straightdope.com/columns/read/2729/why-are-pirates-depicted-with-a-parrot-on-their-shoulder Saturday, October 5, 13
  4. Aim of the talk • Spread the love • Incite

    your curiosity Saturday, October 5, 13
  5. Aim of the talk • Spread the love • Incite

    your curiosity • Solid investment in your career Saturday, October 5, 13
  6. Aim of the talk • Spread the love • Incite

    your curiosity • Solid investment in your career • Front-end development is fun Saturday, October 5, 13
  7. • Model: define properties and behavior • Controller: decorate models

    with display logic • View: reusable UI element • Template: render html Components Saturday, October 5, 13
  8. • Objects are long-lived • E.g the same, singleton controller

    can change models As opposed to server- side MVC ... Saturday, October 5, 13
  9. • Objects are long-lived • E.g the same, singleton controller

    can change models • State is not only maintained in the model layer As opposed to server- side MVC ... Saturday, October 5, 13
  10. Why do you need one? • The classic whole page

    reload is dying out • Users need better & swifter UX Saturday, October 5, 13
  11. Why not just use jQuery? • Apps of non-trivial size

    and/or complexity Saturday, October 5, 13
  12. Why not just use jQuery? • Apps of non-trivial size

    and/or complexity • Sprinkling jQuery selectors only goes that far Saturday, October 5, 13
  13. Why not just use jQuery? • Apps of non-trivial size

    and/or complexity • Sprinkling jQuery selectors only goes that far • Gives structure to your code Saturday, October 5, 13
  14. Why not just use jQuery? • Apps of non-trivial size

    and/or complexity • Sprinkling jQuery selectors only goes that far • Gives structure to your code • Let someone else do the hard stuff Saturday, October 5, 13
  15. Why not just use jQuery? • Apps of non-trivial size

    and/or complexity • Sprinkling jQuery selectors only goes that far • Gives structure to your code • Let someone else do the hard stuff • Less bugs Saturday, October 5, 13
  16. • Backbone • Knockout • Angular • ExtJS • Emberjs

    • ... There are many ... Saturday, October 5, 13
  17. • For building ambitious web applications • Two-way data bindings

    • Computed properties • Routing as a core principle • Convention over Configuration Saturday, October 5, 13
  18. Two-way data bindings {{input type="text" value=firstName}} • Binds two properties

    together • So that one changes, the other gets updated. Saturday, October 5, 13
  19. Computed properties • Property depending on other properties • Gets

    updated iff any of the dependent properties change • Value is cached fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName') Saturday, October 5, 13
  20. Single source of truth • Made possible by bindings and

    computed properties • In your objects • Prevents out-of-sync data • Less code to write and get wrong Saturday, October 5, 13
  21. ”URLs are the UI of the web” Tom Dale, core

    Ember.js member Saturday, October 5, 13
  22. Route hooks • fetch the model • set up controller(s)

    • redirect • ... • very important part of your application App.UserRoute = Ember.Route.extend({ model: function() { return $.getJSON('/user.json'); } }); Saturday, October 5, 13
  23. CoC • Less code to write • “Make a problem

    go away by not doing it the wrong way” (Stefan Penner) Saturday, October 5, 13
  24. TwitterClient::Application.routes.draw do resource :session, only: [:new, :create] resources :timelines root

    to: 'timelines#home' end class SessionsController < ApplicationController def new ... end def create ... end end class TimelinesController < ApplicationController ... end Saturday, October 5, 13
  25. TwitterClient::Application.routes.draw do resource :session, only: [:new, :create] resources :timelines root

    to: 'timelines#home' end class SessionsController < ApplicationController def new ... end def create ... end end class TimelinesController < ApplicationController ... end Saturday, October 5, 13
  26. TwitterClient::Application.routes.draw do resource :session, only: [:new, :create] resources :timelines root

    to: 'timelines#home' end class SessionsController < ApplicationController def new ... end def create ... end end class TimelinesController < ApplicationController ... end Saturday, October 5, 13
  27. App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); App.IndexRoute

    = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  28. App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); App.IndexRoute

    = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  29. App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); App.IndexRoute

    = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  30. App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); App.IndexRoute

    = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  31. App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); App.IndexRoute

    = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  32. App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); App.IndexRoute

    = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  33. App.IndexRoute = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute

    = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  34. App.IndexRoute = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute

    = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  35. App.IndexRoute = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute

    = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); Saturday, October 5, 13
  36. App.IndexRoute = Ember.Route.extend({...}); App.TokenRoute = Ember.Route.extend({...}); App.UserRoute = Ember.Route.extend({...}); App.UserIndexRoute

    = Ember.Route.extend({...}); App.UserTimelineRoute = Ember.Route.extend({...}); App.IndexController = Ember.Controller.extend({...}); App.TokenController = Ember.Controller.extend({...}); App.UserController = Ember.Controller.extend({...}); App.UserIndexController = Ember.ObjectController.extend({...}); App.UserTimelineController = Ember.ObjectController.extend({}); Saturday, October 5, 13
  37. <script ... data-template-name="user"> </script> <script ... data-template-name="user/index"> </script> <script ...

    data-template-name="user/timeline"> </script> App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); Saturday, October 5, 13
  38. <script ... data-template-name="user"> </script> <script ... data-template-name="user/index"> </script> <script ...

    data-template-name="user/timeline"> </script> App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); Saturday, October 5, 13
  39. <script ... data-template-name="user"> </script> <script ... data-template-name="user/index"> </script> <script ...

    data-template-name="user/timeline"> </script> App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); Saturday, October 5, 13
  40. <script ... data-template-name="user"> </script> <script ... data-template-name="user/index"> </script> <script ...

    data-template-name="user/timeline"> </script> App.Router.map(function() { this.route('token'); this.resource('user', function() { this.route('timeline'); }) }); Saturday, October 5, 13