Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Building Do on Heroku
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Austin Bales
March 15, 2012
Programming
740
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Building Do on Heroku
Gopal Patel (@nixme) presents "Building Do on Heroku"
Austin Bales
March 15, 2012
More Decks by Austin Bales
See All by Austin Bales
Design Minded Development
austin
8
540
UI Encapsulation with Handlebars and Sass
austin
5
1.1k
Building Awesome Products at Do.com
austin
2
220
Other Decks in Programming
See All in Programming
R8 の設定見直しでアプリサイズ削減
andpad
0
240
SODA - FACT BOOK(JP)
sodainc
1
40k
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
3
1.8k
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
7.1k
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
250
Jetpack Compose Mechanisms
skydoves
3
900
Spec-Driven Development - Why Vaadin Is the Perfect Fit
simas
PRO
0
180
Kotlinの15年とServer-Side Kotlin
n_takehata
1
170
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
6
2k
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
220
조합이폭발하는디자인시스템이걸눈으로도테스트하라고요
giljongyu
0
650
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
240
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
23k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.6k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
500
Ruling the World: When Life Gets Gamed
codingconduct
0
430
ラッコキーワード サービス紹介資料
rakko
5
5.6M
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
870
Speed Design
sergeychernyshev
33
2.2k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
620
The Pragmatic Product Professional
lauravandoore
37
7.5k
Abbi's Birthday
coloredviolet
4
11k
Transcript
Building Do on Heroku
Gopal Patel, Director of Engineering
[email protected]
• @nixme github.com/nixme
Social Productivity Everywhere “ ”
None
None
SINGLE PAGE
SINGLE PAGE MOBILE FIRST
SINGLE PAGE MOBILE FIRST MANY CLIENTS
↑ ↓ RUBY Heroku Postgres, New Relic, Logplex… ADD-ONS iOS
Android Desktop Widgets CoffeeScript + Backbone.js WEB APPS NATIVE CLIENTS CUSTOM UI FRAMEWORK
API First BEST PRACTICE
API First BEST PRACTICE
Build Platform API First BEST PRACTICE
Build Platform Separation of concerns. Modularity. API First BEST PRACTICE
Build Platform Separation of concerns. Modularity. Constraints lead to guided
design API First BEST PRACTICE
Build Platform Separation of concerns. Modularity. Constraints lead to guided
design Speak HTTP API First BEST PRACTICE
None
def hello puts 'Hello World!' end hello # => Hello
World
class Note include SoftDelete def initialize(title = 'Untitled') @id =
Sequence.next_id @title = title @body = 'Enter your note...' end def print puts "#{@id}: #{@title} - #{@body}" end end
None
VIEW MODEL CONTROLLER BROWSER ↑ ↓ ↑ ↓ ROUTER ↑
↓ ↑ ↓
JSON MODEL CONTROLLER BROWSER ↑ ↓ ↑ ↓ ROUTER ↑
↓ ↑ ↓
Notes Controller RUBY DEMO
The New Age of JS BIG MOVES
None
$('.name').bind('change', function(event) { $.ajax({ type: "PUT", url: "/names/" + $(event.target).attr('context_id'),
data: { value: $(event.target).attr('data-value') }, success: function(response) { statusIcon = $('.name + .status'); statusIcon.show(); setTimeout(function() { statusIcon.hide(); }, 5000); }, error: function(response) { console.log(response); $('.name').attr('disabled', true); } }); }); $('.name_delete').click(function(event) { event.preventDefault(); id = $(event.target).attr('context_id'); if (confirm('Are you sure?')) { $.ajax({ type: "DELETE", url: "/names/" + id, success: function(response) { $(".row-" + id).remove(); $(".row-" + (id + 1)).focus(); },
None
Backbone.Events binds and triggers
Backbone.Events binds and triggers Backbone.Router front-end routing, pushState
Backbone.Events binds and triggers Backbone.Router front-end routing, pushState Backbone.View controllers
for your UI
Backbone.Events binds and triggers Backbone.Router front-end routing, pushState Backbone.View controllers
for your UI Backbone.Model domain objects
Backbone.Events binds and triggers Backbone.Router front-end routing, pushState Backbone.View controllers
for your UI Backbone.Model domain objects Backbone.Collection model sets
var object = {}; _.extend(object, Backbone.Events); object.on("alert", function(msg) { alert("Triggered
" + msg); }); object.trigger("alert", "an event"); Backbone.Events
var Note = Backbone.Model.extend({ initialize: function() {…}, coordinates: function() {…},
}); var note = new Note({ title: "Today's Dinner", body: … }); note.on("error", function(model, error) {…}); note.save(); Backbone.Model
var DocumentRow = Backbone.View.extend({ tagName: "li", className: "document-row", events: {
"click .icon": "open", "click .button.edit": "openEditDialog", "click .button.delete": "destroy" }, render: function() {…} }); Backbone.View
Do’s Router COFFEESCRIPT DEMO
Ember Knockout Spine
None
None
None
number = 42 flag = true greeting = 'world' var
flag, greeting, number; number = 42; flag = true; greeting = 'world';
square = (x) -> x * x cube = (x)
-> x * square x @customer = new Customer $('.cart').on 'click', (event) => @customer.buy event.target var cube, square, _this = this; square = function(x) { return x * x; }; cube = function(x) { return x * square(x); }; this.customer = new Customer; $('.cart').on('click', function(event) { return _this.customer.buy(event.target); });
kids = brother: name: "Max" age: 11 sister: name: "Ida"
age: 9 var kids; kids = { brother: { name: "Max", age: 11 }, sister: { name: "Ida", age: 9 } };
for own view, element of views $(element).remove() view.removed = true
var element, view, __hasProp = Object.prototype.hasOwnProperty; for (view in views) { if (!__hasProp.call(views, view)) continue; element = views[view]; $(element).remove(); view.removed = true; }
coffeescript.org
coffeescript.org sass-lang.com
None
None
BUNDLE (Sprockets) ↓ MINIFY (UglifyJS) COMPRESSION (GZIP) git push ↓
↓
BUNDLE (Sprockets) ↓ MINIFY (UglifyJS) COMPRESSION (GZIP) git push ↓
↓ ↑ ↓ → CLOUDFRONT ↑ ↓
web: unicorn -p $PORT -c ./config/unicorn.rb worker: rake resque:work QUEUE=notifications,...
workerprovisioning: rake resque:work QUEUE=provisioning,... scheduler: rake resque:scheduler VERBOSE=true Procfile
BACKUPS • FORKING • FOLLOWING
None
CONTINUOUS INTEGRATION AUTOMATED TESTING
CONTINUOUS DEPLOYMENT
CONTINUOUS DEPLOYMENT FEATURE FLAGS if Do.Flags.check ‘recurrence’ # Recurring Tasks
Code
Design HOW WE DO
Design HOW WE DO User Experience is #1
Design HOW WE DO User Experience is #1 Engineering +
Design = Like
Design HOW WE DO User Experience is #1 Engineering +
Design = Like Design is a process / conversation
Design HOW WE DO User Experience is #1 Engineering +
Design = Like Design is a process / conversation We work together. Everyone commits.
WHAT WAS THIS TALK ABOUT? API First Expressive Languages Modern
Browsers Continuous Deployment
WHAT WAS THIS TALK ABOUT? API First Expressive Languages Modern
Browsers Continuous Deployment Loosely-coupled Code Tightly-coupled Team
do.com
THE PANEL Manav Monga Product Guy. @xmanav Bing Yang Product
Guy. @bsbox David Yung Developer. @azethoth Austin Bales Designer. @arbales http://pris.ma/9M