Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Aaron Chambers - Ember: when the lights go on
Search
Hey! Presents
April 07, 2015
Technology
0
280
Aaron Chambers - Ember: when the lights go on
Presented at Hey! #16 on 7th April, 2015.
Hey! Presents
April 07, 2015
Tweet
Share
More Decks by Hey! Presents
See All by Hey! Presents
Chris Taylor - Web matters
heypresents
0
480
Doug Winter - Everyone needs a strategy
heypresents
1
220
Paul Berwin - What IP? Whose IP?
heypresents
0
260
Jen Mak - On searching for purpose
heypresents
1
280
Malcolm Slade - The evolution of Google Organic Search
heypresents
0
310
Steve Clarkson - I can't teach you to be a writer
heypresents
0
260
Chris Compston - Design your own career
heypresents
0
300
Emily Cressey - Developers of habit
heypresents
0
280
Stefan McCready - It all started with an anchor tag
heypresents
0
300
Other Decks in Technology
See All in Technology
Yamla: Rustでつくるリアルタイム性を追求した機械学習基盤 / Yamla: A Rust-Based Machine Learning Platform Pursuing Real-Time Capabilities
lycorptech_jp
PRO
3
130
セキュリティの民主化は何故必要なのか_AWS WAF 運用の 10 の苦悩から学ぶ
yoh
1
180
20250625 Snowflake Summit 2025活用事例 レポート / Nowcast Snowflake Summit 2025 Case Study Report
kkuv
1
320
MySQL5.6から8.4へ 戦いの記録
kyoshidaxx
1
260
強化されたAmazon Location Serviceによる新機能と開発者体験
dayjournal
3
220
Oracle Audit Vault and Database Firewall 20 概要
oracle4engineer
PRO
3
1.7k
"サービスチーム" での技術選定 / Making Technology Decisions for the Service Team
kaminashi
1
170
低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 / Building a C Compiler for PHPers Who Want to Dive into Low-Level Programming - Expanded
tomzoh
4
3.3k
作曲家がボカロを使うようにPdMはAIを使え
itotaxi
0
120
生成AI時代 文字コードを学ぶ意義を見出せるか?
hrsued
1
590
登壇ネタの見つけ方 / How to find talk topics
pinkumohikan
5
530
Kotlin Coroutine Mechanisms: A Surprisingly Deep Rabbithole
amanda_hinchman
2
100
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
331
24k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
657
60k
The Pragmatic Product Professional
lauravandoore
35
6.7k
Art, The Web, and Tiny UX
lynnandtonic
299
21k
Visualization
eitanlees
146
16k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Making the Leap to Tech Lead
cromwellryan
134
9.4k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
490
Git: the NoSQL Database
bkeepers
PRO
430
65k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.8k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Why You Should Never Use an ORM
jnunemaker
PRO
58
9.4k
Transcript
ember:&when&the&lights&go&on @grandazz github.com/achambers
developing*since*2000 Javascript Ruby Java$and$Lotus$Notes
github.com/ember.cli/ember.cli.deploy
None
None
Wenguins
None
this%is%not an#ember#is#be(er#than#everything#else presenta(on
browser'dev'boiled'down (shamelessley)borrowed)from)@ryanflorence) interac(ng*with*data*stores rendering'data'to'ui responding*to*user*interac/on router&&&urls project(stuff:(file(organisa3on,(build(tools(etc
None
the$wenguins'$journey$with ember
lightbulb!moments
we#didn't#just#jump#in
we#needed#to validate the$switch
None
None
Service'Status
None
// app/assets/javascripts/application.js function bindViewMoreDetailsLinks() { $('.more-details').hide(); $('.view-more').click(function(e) { e.preventDefault(); var
$viewMoreLink = $(this); var $moreDetails = $viewMoreLink.parents('.issue').find('.more-details'); if ($moreDetails.is(':visible')) { $moreDetails.hide(); $viewMoreLink.text('More details'); } else { $moreDetails.show(); $viewMoreLink.text('Less details'); } $viewMoreLink.toggleClass('opened'); }); }
// app/assets/javascripts/application.js function toggleElementsForEditors() { $.ajax({ url: '/sessions/current', dataType: 'json',
success: function(data) { var loggedInStatus = data.logged_in; toggleNewIssueLink(loggedInStatus); toggleHeader(loggedInStatus); toggleAdditionalLinks(loggedInStatus); toggleSidebar(loggedInStatus); toggleFooter(loggedInStatus); toggleEditIssueLinks(loggedInStatus); toggleResolveIssueLinks(loggedInStatus); } }); }
// app/assets/javascripts/application.js function toggleHeader(loggedInStatus) { $('#skycom-masthead-wrapper').toggleClass('hidden', loggedInStatus); } function toggleAdditionalLinks(loggedInStatus)
{ $('.additional-links').toggleClass('hidden', loggedInStatus); } function toggleSidebar(loggedInStatus) { $('.sidebar').toggleClass('hidden', loggedInStatus); } function toggleFooter(loggedInStatus) { $('#skycom-footer-wrapper').toggleClass('hidden', loggedInStatus); } function toggleEditIssueLinks(loggedInStatus) { $('.btn.edit-issue').toggleClass('hidden', !loggedInStatus); } function toggleResolveIssueLinks(loggedInStatus) { $('.btn.resolve-issue').toggleClass('hidden', !loggedInStatus); }
None
data$based$ui$manipula.on
// app/views/issues/index.html.haml function microfilterCheck() { var deferred = $.Deferred(); $.getJSON('/sessions/current',
function(json) { if (json.logged_in) { deferred.resolve() } else { Hub.runMicrofilterTest() .done(function() { deferred.reject(); }) .fail(function() { deferred.resolve(); }); } }); return deferred; }
// app/views/issues/index.html.haml function restrictionCheck() { var deferred = $.Deferred(); $.getJSON('/customers/current',
function(json) { if (json.customer.has_debt_restriction) { deferred.reject('debt'); } else if (json.customer.has_high_spend_restriction) { deferred.reject('spend'); } else { deferred.resolve(); } }, function() { deferred.resolve(); }); return deferred; }
// app/views/issues/index.html.haml $(function() { var microfilterDeferred = microfilterCheck() var restrictionDeferred
= restrictionCheck() $.when(microfilterDeferred, restrictionDeferred).always(function() { var args = Array.prototype.slice.call(arguments); if (restrictionDeferred.state() == 'rejected') { if (args.indexOf('spend') !== -1) { $('.high-spend-restriction-alert').removeClass('hidden'); } else if (args.indexOf('debt') !== -1) { $('.debt-restriction-alert').removeClass('hidden'); } } else if (microfilterDeferred.state() == 'rejected') { $('.microfilter-alert').removeClass('hidden'); } showIssues(); }); });
then%the%very%next%commit...
// app/views/issues/index.html.haml $(function() { IssuesIndexController.init(); });
None
controllers
// app/assets/javasctipts/User.js var User = { isAnEditor: function() { var
deferred = $.Deferred(); $.ajax({ dataType: 'json', url: '/sessions/current', success: function(data) { deferred.resolve(data.logged_in); }, error: function() { deferred.reject(); } }); return deferred.promise(); } }
// app/assets/javascripts/Diagnostics.js var Diagnostics = { run: function() { //run
some diagnostics goodness } } // app/assets/javascripts/CBS.js var CBS = { run: function() { //run some monstrosity of a service, //return a massive payload we don't need //and take forever to do so } }
None
models & interac(ng*with*data*stores
// app/assets/javascripts/views/IssueView.js (function() { window.IssuesView = { render: function() {
this._showIssues(); this._toggleStatusMessage(); } // ...snip... }; })(); // app/assets/javascripts/views/DebtAlertView.js (function() { window.DebtAlertView = { render: function() { this._showAlert(); this._hideProducts(); this._hideSidebar(); this._informScreenReader(); } // ...snip... }; })();
None
views
{!-- app/assets/javascripts/templates/outages.hbs --}} {{#each outages}} <article class="issue"> <h3>{{description}}</h3> <p> <span
class="label">Date issue was reported</span> </br> <strong>{{startedOn}}</strong> </p> </article> {{/each}}
None
templa'ng
we#started#to#build#our#own#framework
we#started#to#build#our#own#framework BADLY
Use$a$framework,$or$don't.$Either$ way,$you$will. —"Someone"Awesome
conven&on'over'configura&on this.resource('posts', { path: '/posts' }) PostsRoute PostsController PostsView posts.hbs
no#more#globals var Diagnostics = { run: function() { // do
stuff } }; window.IssuesIndexController = { init: function() { // do stuff; } };
no#more#globals#,>#es2015#modules // app/controllers/go-issues.js export default Em.ArrayController.extend({ status: function() { //do
stuff }.property('hasProblem') }); // app/models/outage.js export default DS.Model.extend({ //attributes here }); // app/components/ss-accordion.js export default Em.Component.extend({ collapsed: false, //other properties here });
data$binding // models/tv_issue.js export default DS.Model.extend( name: DS.attr('string') ); //
controllers/tv_issues.js export default Em.ArrayController.extend({ }); <!-- templates/tv_issues.hbs --> <ul> <#each> <li>{{name}}</li> </each> </ul>
lightbulb(moments didn't&stop there
None
None
leave%your%assump-ons at#the#door
None
None
None
None
None
None
None
don't&fight&the&framework
If#something#feels#harder#than#it# should#be,#it#probably#is.#You're# probably#doing#it#wrong. —"Someone"Awesome
None
None
ui#error#logging
ui#error#logging Ember.onerror = handleError; Ember.RSVP.on('error', handleError); function handleError(error) { Em.$.ajax('/error',
{ type: 'POST', data: { stack: error.stack } }); }
None
None
separa&on)of ui#and#api
clearer&separa)on&between&data and$user$interac,on
think¬&of&your&api&in&terms&of&ui& interac2ons,&but&in&terms&of&data& and&rela2onships
your%app%is%a client'of'your'api
None
None
build&tools
build&tools lightening(fast(deployments
build&tools lightening(fast(deployments pact%file%tes*ng
Come%and%chat%to%me
Come%and%chat%to%me at#the#bar tonight
Come%and%chat%to%me Thursday)9th)April 2"Wellington"Place
Aaron&Chambers @grandazz github.com/achambers
any$ques)ons? @grandazz github.com/achambers
thanks'for'having'me