A presentation explaining the web with zero background aimed at brand new developers wanting to build Ruby on Rails applications but not knowing where to start
Call girls Service in Ajman 0505086370 Ajman call girls
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”!
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.
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.
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).
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
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
30.
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!
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?
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
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: