SlideShare a Scribd company logo
From zero to (almost)
Ruby on Rails in about a
million slides.
e.g. How the tubes go with a dash of
Ruby and almost Rails
- Me… Paraphrasing Euclid to King Ptolemy I Soter
“There is no royal road to Rails (or
Geometry)”
Ruby on Rails always seems
to be taught in one fo two
ways:
1. Install Ruby. Install Rails. Type
rails new <project name>. 

Type rails server and then visit http://
localhost:3000. Done. 



or…
2. An introduction to “ActiveRecord”!
NOPE!
The first way doesn’t teach
you how to build anything
in Rails!
… The second way presumes a great deal
of knowledge a new developer may not
have about the web, databases, etc.
The Web
Circa 1999
In 1999 the web was a very simple place.
A web browser loaded a "web page", a static
piece of content from a "web server", whose
only real job was to send files over the
magic internets.
A web page was not a single piece of
content but rather a single HTML file that
may also have some images and links in it.
It also probably had some ordered or
unordered lists of information, a few
paragraphs, and some blinking text.
The web today
e.g. Space LASERs
Fundamentally nothing has changed.
We still have web-servers that pass
files around but…
lots and lots of layers of
"magic" (e.g. technology) stand
between those files and a user
interacting with a website.
Modern "websites" are "web
applications" for the most part.
The distinction between a "site" and
an "application" centers around
dynamic content (e.g. content that
responds to your input as a user)
Applications often maintain "state" that
can be “persisted” e.g. there are users
or accounts or pictures of cats that
remember your name between visits.
The High-Level picture!
e.g. gnomes and unicorns
?
??
Browser
?
We are not going to explain the
"gnomes" in much detail here.
People with titles like "network
engineer" and "infrastructure
engineer” make that happen. (If we
want to dig into that we can do that
another time)
Our real goal here is to have an
intuition for how unicorns (e.g. Web
Applications) work in that picture.
GNOMES!
e.g. HTTP(S)
Gnomes are magical creatures. The
internet feeds on their labor.
One type of very nice Gnome is a
"TCP/IP" gnome. All you need to
know about them is that they work
very very closely with another guild of
Gnomes called “HTTP(S)" Gnomes.
TCP/IP is an internet "protocol" (e.g.
set of rules) for moving data around
in very systematic ways.
One type of data is HTTP(S) data.
HTTP and HTTP(S) are mostly the same.
The latter is encrypted where the prior
is not. (Hint: “S” is for “Secure”)
That's the only real difference so we
will just talk about HTTP here.
Everything we say about HTTP will
_also_ be true of HTTP(S) only
(magically) encrypted.
A reasonable metaphor for the rest of this talk on
Gnomes is that HTTP(S) gnomes hand data to the
TCP/IP Gnomes (Actually, TCP and IP gnomes are
two different sets of Gnomes wearing slightly
different color tunics) who make sure HTTP stuff
goes somewhere and gets back in the way we
expect.
HTTP(S)
Gnomes!
HTTP(S) Gnomes
HTTP is the protocol on which the web works.
It stands for HyperText Transfer Protocol and is the
backbone of the web.
HTTP is actually a very simple protocol at first glance:
HTTP defines verbs.
"Web Servers" are programs that know how to interpret
those verbs and the subjects they act on.
The most important (e.g. fundamental) verb in HTTP is GET
with which you ask a web-server to give you something e.g.
a webpage or an image (or pizza).
The High-Level picture!
e.g. named gnomes and unicorns
GET
?HTTP(S)
Browser
TCP/IP
GET a Pizza!
GET /pizza?topping=extra%20cheese
Hint: %20 is a space on the internet
require 'sinatra'
get '/pizza' do
if params[:topping]
"Sending you a pizza with #{params[:topping]}"
else
"Sending you a cheese pizza!"
end
end
In fact, you can write a _tiny_ Ruby
program using “Sinatra” that makes this
actually work:
$ ruby pizza.rb
== Sinatra/1.4.5 has taken the stage on 4567 for
development with backup from Thin
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
$ curl http://localhost:4567/pizza?topping=extra
%20cheese
Sending you a pizza with extra cheese
In fact, you can write a _tiny_ Ruby
program using “Sinatra” that makes this
actually work:
curl is a "command-line web browser" (handwavey explanation - a
program that “speaks” HTTP and can be used in a terminal).
See the http above? We asked the local server for an unencrypted
request/response (the "request lifecycle").
See the localhost:4567? localhost is your computer (if you use a mac
or linux computer). 4567 is a "port" e.g. a place a program can be
reached by number.
The /pizza looks just like something in the program before I think!
Line 3 perhaps? That's a "route" e.g. a place in your web application
that will return something to you.
And look… the pizza service is sending you something back! I love
the future.
$ curl http://localhost:4567/pizza?topping=extra
%20cheese
Sending you a pizza with extra cheese
“Web
Frameworks”
What even is a
“Framework”?
A “framework” is, loosely speaking, a
collection of programming libraries
aimed at making your life easier in
writing a program. Every language has
them.
Some are "opinionated" e.g. they tell you
how to build programs with them e.g.
their way or the highway (Rails is that).
Some are “general”, they just want to
help somehow (Sinatra is that).
The Request/
Response Lifecycle
We have seen a “request/response
lifecycle" before.
The lifecycle is everything from the
time a browser (like curl) asks a
web-server for something until the
time it gets back and some output is
displayed (mostly).
The Request/Response
Lifecycle (con’t)
In the Sinatra example curl was run, some Gnomes
did their work (even just on your computer) until
a "web server" received the request.
A web-server's job used to be to simply shuttle files
around with Gnomes (TCP/IP and HTTP).
Now its job is to negotiate between requests and
applications which will handle those requests. Then
it can return those application's output to you, the
user. We can see that negotiation in progress…
$ curl -vv localhost:4567/pizza?topping=extra%20cheese
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 4567 (#0)
> GET /pizza?topping=extra%20cheese HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:4567
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Connection: keep-alive
* Server thin is not blacklisted
< Server: thin
<
* Connection #0 to host localhost left intact
Sending you a pizza with extra cheese
From zero to almost rails in about a million slides...
$ curl -vv http://localhost:4567/pizza?topping=extra
%20cheese
Sending you a pizza with extra cheese
In the above we asked curl to be
verbose with -vv (very verbose).
> GET /pizza?topping=extra%20cheese HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:4567
> Accept: */*
>
Our "request" is everything starting
with a > in that big block of
response.
The Request…
> GET /pizza?topping=extra%20cheese HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:4567
> Accept: */*
>
The first line makes the request for
a pizza (with a topping) via GET
and says that we are using HTTP/1.1
(HTTP/2.0 is coming!)
The Request…
> GET /pizza?topping=extra%20cheese HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:4567
> Accept: */*
>
The next line (starting with
User-Agent) is the name and version
of the browser.
The Request…
> GET /pizza?topping=extra%20cheese HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:4567
> Accept: */*
>
The next line is the Host we are
connecting to. Some web-servers
host multiple websites so we could
also be hosting cool-cats-on-the-
internet.com on this server and the
web-server needs to send this
request to the correct application.
The Request…
> GET /pizza?topping=extra%20cheese HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:4567
> Accept: */*
>
The final line can mostly be
ignored right now but says that we
accept any (*/*) response type. It
could be HTML, an image, music, or
anything else.
The Request…
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Connection: keep-alive
* Server thin is not blacklisted
< Server: thin
<
Our "response" is everything
starting with a < in the original
The Response!
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< … SNIP
<
The parts we are going to talk
about are much fewer!
The Response!
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< … SNIP
<
The first line is the most important
- It says that the response is also
an HTTP/1.1 response.
The Response!
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< … SNIP
<
200 and OK are actually the same
thing! And they are good news!
The Response!
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< … SNIP
<
200 is a "response code" e.g. a
numeric response (for computers)
saying that the request worked as
expected where the OK is the human
version of that message. Cool!
The Response!
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< … SNIP
<
The next line says that the server is
sending HTML and that it might
contain non-latin characters (that's
the utf-8 part). We said we accept
*/* so HTML should be fine.
The Response!
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 39
< … SNIP
<
After that the Content-Length tells
curl how much data to expect.
The Response!
Whew!
That is a
complete and
working web-
application…
and… an entire
request/response
lifecycle.
There’s one little
problem!
Especially since…
<HTML>
<BODY>
<p>Sending you a pizza with extra cheese</p>
</BODY>
</HTML>
What we said we were returning was
text/html but what we returned was
some text. HTML looks like this:
but we sent
Sending you a pizza with extra cheese
require 'sinatra'
get '/pizza' do
copy = if params[:topping]
topping = params[:topping]
"Sending you a pizza with #{topping}"
else
"Sending you a cheese pizza!"
end
"<HTML><BODY><p>#{copy}</p></BODY></HTML>"
end
Let's update our program to include
some HTML instead!
$ curl localhost:4567/pizza?topping=extra
%20cheese
<HTML><BODY><p>Sending you a pizza with extra
cheese</p></BODY></HTML>
And run it again…
YAY! HTML!
The next
problem….
(is not just cheesy
clip-art)
One can imagine that as your
application grows, hand rolling
(almost identical) HTML for a whole
bunch of "routes" might get tedious.
If you are building not just a pizza
delivery site but rather an Italian
restaurant site you might have
something that looks like…
require 'sinatra'
get '/pizza' do
# some code
end
get '/calzone' do
# some code
end
get '/spaghetti' do
# some code
end
get '/linguine' do
end
get '/antipasto' do
end
### the stereotypical menu may continue ad-infinitum
Paring down the
menu
One of the first things you probably want
to do is get rid of the boiler-plate HTML
and just put in the <p>#{copy}</p> for each
of those routes.
Sinatra has a convention that if a file
called views/layout.erb exists it will use it
for the boiler-plate!
Let's do that!
Create your layout
<HTML>
<BODY>
<%= yield %>
</BODY>
</HTML>
Where you see <%= yield => is where
your copy will be placed.
The above is a special templating
language called ERB that lets you
put Ruby in it!
require 'sinatra'
get '/pizza' do
copy = if params[:topping]
topping = params[:topping]
"Sending you a pizza with #{topping}"
else
"Sending you a cheese pizza!"
end
erb “<p>#{copy}</p>" # here we use the layout
end
Let's update our program to use our new
layout!
Frameworks! (con’t)
This is the beginning of the power of a framework: Sinatra
knows that if there is a file called views/layout.erb and you call
erb with a parameter, that parameter should be put in the layout
where yield is called there.
This "knowledge" is known as "Convention over Configuration".
In Sinatra (and Rails) assumptions (conventions) are made by
the framework designer. You can override them if you have a
good reason but very often you don’t have to (and shouldn’t and
that's awesome).
Conventions are also where the reputation of these frameworks
for "doing magic" comes from.
Let’s Model a thing!
We've done good work - We’ve simplified our 

/pizza route by removing some boiler-plate.
The next step might be to simplify the route by
moving the topping logic somewhere.
The reasoning here is that each route will have
some logic and it will make the original file
_really_ long.
Let's just start by moving the logic out into a Class!
require 'sinatra'
class Pizza
def initialize(topping=nil)
@topping = topping
end
def order_copy
if @topping
"Sending you a pizza with #{@topping}"
else
"Sending you a cheese pizza!"
end
end
end
get '/pizza' do
pizza = Pizza.new(params[:topping])
erb "<p>#{pizza.order_copy}</p>"
end
Yay for Models
This is awesome because now we've
made the logic in the "route" so
simple: Just build a pizza, ask it to
build its own copy, and send it back!
But that class is long so maybe we
can move it somewhere else and just
reference it here?
e.g.
Oh no!!!
I made the code LONGER!
More is Less
The lessons of Classes ond Object-
Oriented Programming
The very very very
short version
A major goal of Object-Oriented
Programming is to contain all of
the logic about a type of thing and
put it in its own isolated
description (abstraction and
encapsulation) that can be used over
and over.
But why?
Anytime we have to think about a
Pizza we look in one place: the
Pizza class definition.
Other things like Calzones or
Linguine can have their own classes
for the same reason.
So let’s make it
shorter again
Just like we put the “layout” in
views/layout.erb we can create our
own convention of putting classes
in a models/ directory.
Sinatra does not have its own
convention for models so we’re
making one to stick to!
“Extract” your
Model!
class Pizza
def initialize(topping=nil)
@topping = topping
end
def order_copy
if @topping
"Sending you a pizza with #{@topping}"
else
"Sending you a cheese pizza!"
end
end
end
models/pizza.rb
When a developer
says…
“extract” it just means cut/paste the
code from one place into another to
simplify the prior and (usually)
create the latter.
“better” they mean they have an
opinion. It is probably right or
wrong.
Use your model!
require 'sinatra'
require './models/pizza.rb'
# ^^ pull the model into our code here!
get '/pizza' do
pizza = Pizza.new(params[:topping])
erb "<p>#{pizza.order_copy}</p>"
end
We’ve Built Rails!
Sorta. Kinda. In a _really_ minimal
form.
Much segue. Such
Rails. Wow
We have now built what might be
considered a very minimal Rails
application without talking about Rails
at all!
We simply (and iteratively) used some
sane conventions to simplify one thing
at a time and put them in un-
surprising places.
That is _exactly_ how Rails came to
be.
David Heinemeier Hansson built a
Ruby web-application. Then he tore
out all of the generic stuff into his
own Framework called Rails
(warning you not to go off them!)
It exploded (into pure awesomeness)
from there.
Yeah… so show me.
(Remember slide 2?) If we had Rails
installed and typed rails new
italian_restaurant we would find a
whole bunch of files and directories
that Rails thinks we want and need.
These are the conventional files of
Rails.
Let's look at a small subset of them:
RAILS! Behold!
italian_restaurant/
app/
models/
views/
layouts/
application.html.erb
config/
routes.rb
... Many many more.
This should look
_really_ familiar!
Guess what is in app/models/ ?
Guess what is in app/views/layouts/ ?
Guess what is config/routes.rb ?
Next up…
Rails for
Reals
but you probably look
like this:

More Related Content

PDF
HTTP/2 BrightonSEO 2018
PDF
IBM dwLive, "Internet & HTTP - 잃어버린 패킷을 찾아서..."
PDF
OSMC 2018 | Handling messages and notifications from software and gadgets wit...
PPTX
Comet Server Push Over Web
PDF
Ilugc curl
PDF
Introduction HTTP via cURL
PDF
Hack the box open admin writeup
PDF
SearchLove San Diego 2018 | Tom Anthony | An Introduction to HTTP/2 & Service...
HTTP/2 BrightonSEO 2018
IBM dwLive, "Internet & HTTP - 잃어버린 패킷을 찾아서..."
OSMC 2018 | Handling messages and notifications from software and gadgets wit...
Comet Server Push Over Web
Ilugc curl
Introduction HTTP via cURL
Hack the box open admin writeup
SearchLove San Diego 2018 | Tom Anthony | An Introduction to HTTP/2 & Service...

What's hot (20)

PDF
Web tech 101
PDF
神に近づくx/net/context (Finding God with x/net/context)
KEY
Operation Oriented Web Applications / Yokohama pm7
PDF
Reachability in Mobile App Development
PDF
Transforming WebSockets
PPT
Html5, css3, canvas, svg and webgl
PDF
WebShell - confoo 2011 - sean coates
KEY
Building A Gem From Scratch
PPT
Web Scraper Shibuya.pm tech talk #8
PPTX
PyConMY 2016 Django Channels
PDF
Introduction to REST and JAX-RS
KEY
Intro To Advanced Ruby
PDF
Ruby HTTP clients comparison
PDF
Scrip queue tree
PDF
Cors michael
KEY
Push the web with HTML5
PPT
Breaking The Cross Domain Barrier
PDF
PHP And Web Services: Perfect Partners
PDF
5. HTTP и приятели
PDF
Ruby HTTP clients
Web tech 101
神に近づくx/net/context (Finding God with x/net/context)
Operation Oriented Web Applications / Yokohama pm7
Reachability in Mobile App Development
Transforming WebSockets
Html5, css3, canvas, svg and webgl
WebShell - confoo 2011 - sean coates
Building A Gem From Scratch
Web Scraper Shibuya.pm tech talk #8
PyConMY 2016 Django Channels
Introduction to REST and JAX-RS
Intro To Advanced Ruby
Ruby HTTP clients comparison
Scrip queue tree
Cors michael
Push the web with HTML5
Breaking The Cross Domain Barrier
PHP And Web Services: Perfect Partners
5. HTTP и приятели
Ruby HTTP clients
Ad

Viewers also liked (7)

PDF
Digital Ocean Presentation - Ruby Dev Stackup - The Flatiron School
PDF
DigitalOceanことはじめ
PPTX
Stampede.io CoreOS + Digital Ocean Meetup
PPTX
Scaling Cloud Networking at DigitalOcean from ThousandEyes Connect
PDF
Scaling on DigitalOcean
PPTX
Deploying a Ruby on Rails App with Digital Ocean
PPTX
The good, bad and ugly of Digital Ocean vs AWS
Digital Ocean Presentation - Ruby Dev Stackup - The Flatiron School
DigitalOceanことはじめ
Stampede.io CoreOS + Digital Ocean Meetup
Scaling Cloud Networking at DigitalOcean from ThousandEyes Connect
Scaling on DigitalOcean
Deploying a Ruby on Rails App with Digital Ocean
The good, bad and ugly of Digital Ocean vs AWS
Ad

Similar to From zero to almost rails in about a million slides... (20)

PPTX
Socket programming with php
PDF
Real-Time with Flowdock
PPTX
Web server working
ODP
Wifi Security, or Descending into Depression and Drink
PPTX
Kiwipycon command line
PDF
Introduction to programming - class 8
PPTX
Pythonlearn-12-HTTP- Network Programming
PDF
Python tools for testing web services over HTTP
PPTX
How does internet works
PDF
Crypto workshop part 1 - Web and Crypto
PDF
Command & [e]Mission Control: Using Command and Event Buses to create a CQRS-...
PPTX
Servlet & jsp
PDF
Why and How to use Onion Networking - #EMFCamp2018
PPT
Intro to PHP for Students and professionals
PPTX
Interactive web. O rly?
PDF
Web tcp ip
PDF
Server-Sent Events (real-time HTTP push for HTML5 browsers)
PDF
Sinatra: прошлое, будущее и настоящее
KEY
node.js: Javascript's in your backend
PPTX
How Internet Works
Socket programming with php
Real-Time with Flowdock
Web server working
Wifi Security, or Descending into Depression and Drink
Kiwipycon command line
Introduction to programming - class 8
Pythonlearn-12-HTTP- Network Programming
Python tools for testing web services over HTTP
How does internet works
Crypto workshop part 1 - Web and Crypto
Command & [e]Mission Control: Using Command and Event Buses to create a CQRS-...
Servlet & jsp
Why and How to use Onion Networking - #EMFCamp2018
Intro to PHP for Students and professionals
Interactive web. O rly?
Web tcp ip
Server-Sent Events (real-time HTTP push for HTML5 browsers)
Sinatra: прошлое, будущее и настоящее
node.js: Javascript's in your backend
How Internet Works

Recently uploaded (20)

PPTX
introduction about ICD -10 & ICD-11 ppt.pptx
PPTX
Introuction about WHO-FIC in ICD-10.pptx
PPTX
SAP Ariba Sourcing PPT for learning material
PPTX
Introduction to Information and Communication Technology
PDF
Testing WebRTC applications at scale.pdf
PPT
tcp ip networks nd ip layering assotred slides
PPTX
PptxGenJS_Demo_Chart_20250317130215833.pptx
PDF
An introduction to the IFRS (ISSB) Stndards.pdf
PPTX
QR Codes Qr codecodecodecodecocodedecodecode
PPTX
522797556-Unit-2-Temperature-measurement-1-1.pptx
PDF
Slides PDF The World Game (s) Eco Economic Epochs.pdf
PDF
APNIC Update, presented at PHNOG 2025 by Shane Hermoso
PPTX
Introduction about ICD -10 and ICD11 on 5.8.25.pptx
PPTX
Module 1 - Cyber Law and Ethics 101.pptx
PPTX
Introuction about ICD -10 and ICD-11 PPT.pptx
PDF
Cloud-Scale Log Monitoring _ Datadog.pdf
PPTX
Slides PPTX World Game (s) Eco Economic Epochs.pptx
PPTX
international classification of diseases ICD-10 review PPT.pptx
PDF
Best Practices for Testing and Debugging Shopify Third-Party API Integrations...
PDF
Triggering QUIC, presented by Geoff Huston at IETF 123
introduction about ICD -10 & ICD-11 ppt.pptx
Introuction about WHO-FIC in ICD-10.pptx
SAP Ariba Sourcing PPT for learning material
Introduction to Information and Communication Technology
Testing WebRTC applications at scale.pdf
tcp ip networks nd ip layering assotred slides
PptxGenJS_Demo_Chart_20250317130215833.pptx
An introduction to the IFRS (ISSB) Stndards.pdf
QR Codes Qr codecodecodecodecocodedecodecode
522797556-Unit-2-Temperature-measurement-1-1.pptx
Slides PDF The World Game (s) Eco Economic Epochs.pdf
APNIC Update, presented at PHNOG 2025 by Shane Hermoso
Introduction about ICD -10 and ICD11 on 5.8.25.pptx
Module 1 - Cyber Law and Ethics 101.pptx
Introuction about ICD -10 and ICD-11 PPT.pptx
Cloud-Scale Log Monitoring _ Datadog.pdf
Slides PPTX World Game (s) Eco Economic Epochs.pptx
international classification of diseases ICD-10 review PPT.pptx
Best Practices for Testing and Debugging Shopify Third-Party API Integrations...
Triggering QUIC, presented by Geoff Huston at IETF 123

From zero to almost rails in about a million slides...

  • 1. From zero to (almost) Ruby on Rails in about a million slides. e.g. How the tubes go with a dash of Ruby and almost Rails
  • 2. - Me… Paraphrasing Euclid to King Ptolemy I Soter “There is no royal road to Rails (or Geometry)”
  • 3. Ruby on Rails always seems to be taught in one fo two ways: 1. Install Ruby. Install Rails. Type rails new <project name>. 
 Type rails server and then visit http:// localhost:3000. Done. 
 
 or… 2. An introduction to “ActiveRecord”!
  • 5. The first way doesn’t teach you how to build anything in Rails!
  • 6. … The second way presumes a great deal of knowledge a new developer may not have about the web, databases, etc.
  • 8. In 1999 the web was a very simple place. A web browser loaded a "web page", a static piece of content from a "web server", whose only real job was to send files over the magic internets. A web page was not a single piece of content but rather a single HTML file that may also have some images and links in it. It also probably had some ordered or unordered lists of information, a few paragraphs, and some blinking text.
  • 9. The web today e.g. Space LASERs
  • 10. Fundamentally nothing has changed. We still have web-servers that pass files around but… lots and lots of layers of "magic" (e.g. technology) stand between those files and a user interacting with a website.
  • 11. Modern "websites" are "web applications" for the most part. The distinction between a "site" and an "application" centers around dynamic content (e.g. content that responds to your input as a user) Applications often maintain "state" that can be “persisted” e.g. there are users or accounts or pictures of cats that remember your name between visits.
  • 12. The High-Level picture! e.g. gnomes and unicorns ? ?? Browser ?
  • 13. We are not going to explain the "gnomes" in much detail here. People with titles like "network engineer" and "infrastructure engineer” make that happen. (If we want to dig into that we can do that another time) Our real goal here is to have an intuition for how unicorns (e.g. Web Applications) work in that picture.
  • 15. Gnomes are magical creatures. The internet feeds on their labor. One type of very nice Gnome is a "TCP/IP" gnome. All you need to know about them is that they work very very closely with another guild of Gnomes called “HTTP(S)" Gnomes. TCP/IP is an internet "protocol" (e.g. set of rules) for moving data around in very systematic ways.
  • 16. One type of data is HTTP(S) data. HTTP and HTTP(S) are mostly the same. The latter is encrypted where the prior is not. (Hint: “S” is for “Secure”) That's the only real difference so we will just talk about HTTP here. Everything we say about HTTP will _also_ be true of HTTP(S) only (magically) encrypted.
  • 17. A reasonable metaphor for the rest of this talk on Gnomes is that HTTP(S) gnomes hand data to the TCP/IP Gnomes (Actually, TCP and IP gnomes are two different sets of Gnomes wearing slightly different color tunics) who make sure HTTP stuff goes somewhere and gets back in the way we expect.
  • 19. HTTP(S) Gnomes HTTP is the protocol on which the web works. It stands for HyperText Transfer Protocol and is the backbone of the web. HTTP is actually a very simple protocol at first glance: HTTP defines verbs. "Web Servers" are programs that know how to interpret those verbs and the subjects they act on. The most important (e.g. fundamental) verb in HTTP is GET with which you ask a web-server to give you something e.g. a webpage or an image (or pizza).
  • 20. The High-Level picture! e.g. named gnomes and unicorns GET ?HTTP(S) Browser TCP/IP
  • 21. GET a Pizza! GET /pizza?topping=extra%20cheese Hint: %20 is a space on the internet
  • 22. require 'sinatra' get '/pizza' do if params[:topping] "Sending you a pizza with #{params[:topping]}" else "Sending you a cheese pizza!" end end In fact, you can write a _tiny_ Ruby program using “Sinatra” that makes this actually work:
  • 23. $ ruby pizza.rb == Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Thin Thin web server (v1.6.3 codename Protein Powder) Maximum connections set to 1024 Listening on localhost:4567, CTRL+C to stop $ curl http://localhost:4567/pizza?topping=extra %20cheese Sending you a pizza with extra cheese In fact, you can write a _tiny_ Ruby program using “Sinatra” that makes this actually work:
  • 24. curl is a "command-line web browser" (handwavey explanation - a program that “speaks” HTTP and can be used in a terminal). See the http above? We asked the local server for an unencrypted request/response (the "request lifecycle"). See the localhost:4567? localhost is your computer (if you use a mac or linux computer). 4567 is a "port" e.g. a place a program can be reached by number. The /pizza looks just like something in the program before I think! Line 3 perhaps? That's a "route" e.g. a place in your web application that will return something to you. And look… the pizza service is sending you something back! I love the future. $ curl http://localhost:4567/pizza?topping=extra %20cheese Sending you a pizza with extra cheese
  • 25. “Web Frameworks” What even is a “Framework”?
  • 26. A “framework” is, loosely speaking, a collection of programming libraries aimed at making your life easier in writing a program. Every language has them. Some are "opinionated" e.g. they tell you how to build programs with them e.g. their way or the highway (Rails is that). Some are “general”, they just want to help somehow (Sinatra is that).
  • 27. The Request/ Response Lifecycle We have seen a “request/response lifecycle" before. The lifecycle is everything from the time a browser (like curl) asks a web-server for something until the time it gets back and some output is displayed (mostly).
  • 28. The Request/Response Lifecycle (con’t) In the Sinatra example curl was run, some Gnomes did their work (even just on your computer) until a "web server" received the request. A web-server's job used to be to simply shuttle files around with Gnomes (TCP/IP and HTTP). Now its job is to negotiate between requests and applications which will handle those requests. Then it can return those application's output to you, the user. We can see that negotiation in progress…
  • 29. $ curl -vv localhost:4567/pizza?topping=extra%20cheese * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 4567 (#0) > GET /pizza?topping=extra%20cheese HTTP/1.1 > User-Agent: curl/7.37.1 > Host: localhost:4567 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < Connection: keep-alive * Server thin is not blacklisted < Server: thin < * Connection #0 to host localhost left intact Sending you a pizza with extra cheese
  • 31. $ curl -vv http://localhost:4567/pizza?topping=extra %20cheese Sending you a pizza with extra cheese In the above we asked curl to be verbose with -vv (very verbose).
  • 32. > GET /pizza?topping=extra%20cheese HTTP/1.1 > User-Agent: curl/7.37.1 > Host: localhost:4567 > Accept: */* > Our "request" is everything starting with a > in that big block of response. The Request…
  • 33. > GET /pizza?topping=extra%20cheese HTTP/1.1 > User-Agent: curl/7.37.1 > Host: localhost:4567 > Accept: */* > The first line makes the request for a pizza (with a topping) via GET and says that we are using HTTP/1.1 (HTTP/2.0 is coming!) The Request…
  • 34. > GET /pizza?topping=extra%20cheese HTTP/1.1 > User-Agent: curl/7.37.1 > Host: localhost:4567 > Accept: */* > The next line (starting with User-Agent) is the name and version of the browser. The Request…
  • 35. > GET /pizza?topping=extra%20cheese HTTP/1.1 > User-Agent: curl/7.37.1 > Host: localhost:4567 > Accept: */* > The next line is the Host we are connecting to. Some web-servers host multiple websites so we could also be hosting cool-cats-on-the- internet.com on this server and the web-server needs to send this request to the correct application. The Request…
  • 36. > GET /pizza?topping=extra%20cheese HTTP/1.1 > User-Agent: curl/7.37.1 > Host: localhost:4567 > Accept: */* > The final line can mostly be ignored right now but says that we accept any (*/*) response type. It could be HTML, an image, music, or anything else. The Request…
  • 37. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < Connection: keep-alive * Server thin is not blacklisted < Server: thin < Our "response" is everything starting with a < in the original The Response!
  • 38. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < … SNIP < The parts we are going to talk about are much fewer! The Response!
  • 39. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < … SNIP < The first line is the most important - It says that the response is also an HTTP/1.1 response. The Response!
  • 40. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < … SNIP < 200 and OK are actually the same thing! And they are good news! The Response!
  • 41. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < … SNIP < 200 is a "response code" e.g. a numeric response (for computers) saying that the request worked as expected where the OK is the human version of that message. Cool! The Response!
  • 42. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < … SNIP < The next line says that the server is sending HTML and that it might contain non-latin characters (that's the utf-8 part). We said we accept */* so HTML should be fine. The Response!
  • 43. < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 39 < … SNIP < After that the Content-Length tells curl how much data to expect. The Response!
  • 44. Whew! That is a complete and working web- application… and… an entire request/response lifecycle.
  • 46. <HTML> <BODY> <p>Sending you a pizza with extra cheese</p> </BODY> </HTML> What we said we were returning was text/html but what we returned was some text. HTML looks like this: but we sent Sending you a pizza with extra cheese
  • 47. require 'sinatra' get '/pizza' do copy = if params[:topping] topping = params[:topping] "Sending you a pizza with #{topping}" else "Sending you a cheese pizza!" end "<HTML><BODY><p>#{copy}</p></BODY></HTML>" end Let's update our program to include some HTML instead!
  • 48. $ curl localhost:4567/pizza?topping=extra %20cheese <HTML><BODY><p>Sending you a pizza with extra cheese</p></BODY></HTML> And run it again… YAY! HTML!
  • 49. The next problem…. (is not just cheesy clip-art)
  • 50. One can imagine that as your application grows, hand rolling (almost identical) HTML for a whole bunch of "routes" might get tedious. If you are building not just a pizza delivery site but rather an Italian restaurant site you might have something that looks like…
  • 51. require 'sinatra' get '/pizza' do # some code end get '/calzone' do # some code end get '/spaghetti' do # some code end get '/linguine' do end get '/antipasto' do end ### the stereotypical menu may continue ad-infinitum
  • 52. Paring down the menu One of the first things you probably want to do is get rid of the boiler-plate HTML and just put in the <p>#{copy}</p> for each of those routes. Sinatra has a convention that if a file called views/layout.erb exists it will use it for the boiler-plate! Let's do that!
  • 53. Create your layout <HTML> <BODY> <%= yield %> </BODY> </HTML> Where you see <%= yield => is where your copy will be placed. The above is a special templating language called ERB that lets you put Ruby in it!
  • 54. require 'sinatra' get '/pizza' do copy = if params[:topping] topping = params[:topping] "Sending you a pizza with #{topping}" else "Sending you a cheese pizza!" end erb “<p>#{copy}</p>" # here we use the layout end Let's update our program to use our new layout!
  • 55. Frameworks! (con’t) This is the beginning of the power of a framework: Sinatra knows that if there is a file called views/layout.erb and you call erb with a parameter, that parameter should be put in the layout where yield is called there. This "knowledge" is known as "Convention over Configuration". In Sinatra (and Rails) assumptions (conventions) are made by the framework designer. You can override them if you have a good reason but very often you don’t have to (and shouldn’t and that's awesome). Conventions are also where the reputation of these frameworks for "doing magic" comes from.
  • 56. Let’s Model a thing! We've done good work - We’ve simplified our 
 /pizza route by removing some boiler-plate. The next step might be to simplify the route by moving the topping logic somewhere. The reasoning here is that each route will have some logic and it will make the original file _really_ long. Let's just start by moving the logic out into a Class!
  • 57. require 'sinatra' class Pizza def initialize(topping=nil) @topping = topping end def order_copy if @topping "Sending you a pizza with #{@topping}" else "Sending you a cheese pizza!" end end end get '/pizza' do pizza = Pizza.new(params[:topping]) erb "<p>#{pizza.order_copy}</p>" end
  • 58. Yay for Models This is awesome because now we've made the logic in the "route" so simple: Just build a pizza, ask it to build its own copy, and send it back! But that class is long so maybe we can move it somewhere else and just reference it here?
  • 59. e.g. Oh no!!! I made the code LONGER!
  • 60. More is Less The lessons of Classes ond Object- Oriented Programming
  • 61. The very very very short version A major goal of Object-Oriented Programming is to contain all of the logic about a type of thing and put it in its own isolated description (abstraction and encapsulation) that can be used over and over.
  • 62. But why? Anytime we have to think about a Pizza we look in one place: the Pizza class definition. Other things like Calzones or Linguine can have their own classes for the same reason.
  • 63. So let’s make it shorter again Just like we put the “layout” in views/layout.erb we can create our own convention of putting classes in a models/ directory. Sinatra does not have its own convention for models so we’re making one to stick to!
  • 64. “Extract” your Model! class Pizza def initialize(topping=nil) @topping = topping end def order_copy if @topping "Sending you a pizza with #{@topping}" else "Sending you a cheese pizza!" end end end models/pizza.rb
  • 65. When a developer says… “extract” it just means cut/paste the code from one place into another to simplify the prior and (usually) create the latter. “better” they mean they have an opinion. It is probably right or wrong.
  • 66. Use your model! require 'sinatra' require './models/pizza.rb' # ^^ pull the model into our code here! get '/pizza' do pizza = Pizza.new(params[:topping]) erb "<p>#{pizza.order_copy}</p>" end
  • 67. We’ve Built Rails! Sorta. Kinda. In a _really_ minimal form.
  • 68. Much segue. Such Rails. Wow We have now built what might be considered a very minimal Rails application without talking about Rails at all! We simply (and iteratively) used some sane conventions to simplify one thing at a time and put them in un- surprising places.
  • 69. That is _exactly_ how Rails came to be. David Heinemeier Hansson built a Ruby web-application. Then he tore out all of the generic stuff into his own Framework called Rails (warning you not to go off them!) It exploded (into pure awesomeness) from there.
  • 71. (Remember slide 2?) If we had Rails installed and typed rails new italian_restaurant we would find a whole bunch of files and directories that Rails thinks we want and need. These are the conventional files of Rails. Let's look at a small subset of them:
  • 73. This should look _really_ familiar! Guess what is in app/models/ ? Guess what is in app/views/layouts/ ? Guess what is config/routes.rb ?
  • 74. Next up… Rails for Reals but you probably look like this: