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
240
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
420
Doug Winter - Everyone needs a strategy
heypresents
1
170
Paul Berwin - What IP? Whose IP?
heypresents
0
200
Jen Mak - On searching for purpose
heypresents
1
230
Malcolm Slade - The evolution of Google Organic Search
heypresents
0
230
Steve Clarkson - I can't teach you to be a writer
heypresents
0
200
Chris Compston - Design your own career
heypresents
0
260
Emily Cressey - Developers of habit
heypresents
0
230
Stefan McCready - It all started with an anchor tag
heypresents
0
240
Other Decks in Technology
See All in Technology
Application Development WG Intro at AppDeveloperCon
salaboy
0
180
安心してください、日本語使えますよ―Ubuntu日本語Remix提供休止に寄せて― 2024-11-17
nobutomurata
1
990
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
2
1.6k
リンクアンドモチベーション ソフトウェアエンジニア向け紹介資料 / Introduction to Link and Motivation for Software Engineers
lmi
4
300k
iOSチームとAndroidチームでブランチ運用が違ったので整理してます
sansantech
PRO
0
130
スクラム成熟度セルフチェックツールを作って得た学びとその活用法
coincheck_recruit
1
140
社内で最大の技術的負債のリファクタリングに取り組んだお話し
kidooonn
1
550
開発生産性を上げながらビジネスも30倍成長させてきたチームの姿
kamina_zzz
2
1.7k
ExaDB-D dbaascli で出来ること
oracle4engineer
PRO
0
3.8k
Can We Measure Developer Productivity?
ewolff
1
150
AGIについてChatGPTに聞いてみた
blueb
0
130
これまでの計測・開発・デプロイ方法全部見せます! / Findy ISUCON 2024-11-14
tohutohu
3
370
Featured
See All Featured
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
370
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
Speed Design
sergeychernyshev
24
610
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
Fireside Chat
paigeccino
34
3k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
The Invisible Side of Design
smashingmag
298
50k
Into the Great Unknown - MozCon
thekraken
32
1.5k
Unsuck your backbone
ammeep
668
57k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
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