HTTP
HTTP is a protocol that is allowed you to communicate with other people(computer) through this protocol. Therefore, you have to obey some rules. And every computer has an ip address
, but it is difficult for us to remember. Here comes DNS
, domain naming system. You can built your own DNS server or use your internet supplier or Google’s server. It can help you to transform naming address to ip address then the computer know where to go. for example, you type in www.google.com
, then it will sent to DNS server
to identify where the ip address
is.
client and server
All websites are built on the server. every computer can be a server. We use the browser
to send request
to server
then it send back to us wiht some response
. All the response may includes files, images, web pages. There are name with resources
. request
needs method
and path
. header
and body
are optional. response
with status code
is required. header
and body
are optional.
Stateless
server
can not deal with lots of states coming from the client
; therefore, all the Internet are agreed to use stateless
way to handle the data. Everytime client
sending request
with server
back with response
is individual. It will sent back all the information we need to do next round to the clients, if the client
make some change, then next time, the response will send back the following change to the client
. In short, server
keeps no information about these state.
URL, uniform resource locator
http://www.example.com:88/home?item=book
http
is scheme, a protocolwww.example.com
is host88
is port/home
is the path?item=book
isquery parameters
Some thought on Sinatra
What is reloader?
sinatra/reloader
is part of Sinatra::Contrib project
. It helps user to quick reload pages while developing.
Useful during development, since it will automatically require files defining routes, filters, error handlers and inline templates, with every incoming request, but only if they have been updated.
require "sinatra"
require "sinatra/reloader" if development?
# Your classic application code goes here...
wat is Tilt?
-
It is an all-inclusive wrapper gem for Ruby template engine, you can view its github page.
- In the [Erubis User guide](http://www.kuwata-lab.com/erubis/users-guide.html) lists its benefits:
- Very fast, almost three times faster than ERB and about ten percent faster than eruby (implemented in C)
- File caching of converted Ruby script support
- Auto escaping support, etc.
- So use
require tilt/erubis
will render much faster than built-in erb.
Partition method and Taking block explicitly
In the course of understanding Sinatra. I learn some new method in this course.
-
understand
Enumerable::partition
-
understand
&block
andyield
Although it is the previous course. But there is no enough true example. Only some exercise. So I think it is a good way to practice here.
yield to the block, passing in the current element to the block
. Inside the method
, The yield
keyword executes the block.
- yield with an argument:
execution is yielded to the block (or the block is called), and we’re passing
argument
to the block.
Every method, regardless of its method definition, takes an implicit block (though, it may just ignore the implicit block). Sometimes, you’ll want to implement a method that explicitly takes a block.
At first, I am a little confused with &block
. If method
in Ruby can take block implicitly, why we have to do it with &block
? Until I was working with this project, then I understand the reason why we have to sometimes take block explicitly. This one is very good example that we do have to take block explicitly.
# partition { |obj| block } → [ true_array, false_array ]
# partition → an_enumerator
# Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.
# If no block is given, an enumerator is returned instead.
(1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
<ul id="lists">
<% sort_lists @lists do |list, index| %>
<li class="<%= list_class(list)%>">
<a href="/lists/<%= index %>">
<h2><%= list[:name] %></h2>
<p>
<%= todos_remaining_count(list) %> / <%= todos_count(list) %>
</p>
</a>
</li>
<% end %>
</ul>
- Before using Ruby built-in function
partition
:
def sort_lists(list, &block)
incomplete_lists = {}
complete_lists = {}
lists.each_with_index do |list, index|
if list_complete?(list)
complete_lists[list] = index
else
incomplete_lists[list] = index
end
incomplete_lists.each(&block)
complete_lists.each(&block)
end
end
- After using
partition
method:
def sort_lists(lists, &block)
complete_list, incomplete_list = lists.partition { |list| list_complete?(list) }
complete_list.each { |list| yield(list, lists.index(list)) }
incomplete_list.each { |list| yield(list, lists.index(list)) }
end
Reading YAML
Ruby versions >= 2.0 have a new YAML implementation provided by a library called Psych. When you require “yaml” to load the
YAML
object, you are actually getting a handle onPsych
Writing Sinatra in OOP way
- Use Sinatra::Base
- use some helpers from external files
for example:
# my_app.rb
require 'sinatra/base'
require 'sinatra/some_helpers'
class MyApp < Sinatra::Base
helpers Sinatra::SomeHelpers
...
end
When to use config.ru?
from the Readme Page in Sinatra Documentation:
A config.ru file is recommended if:
- You want to deploy with a different Rack handler (Passenger, Unicorn, Heroku, …).
- You want to use more than one subclass of Sinatra::Base.
- You want to use Sinatra only for middleware, and not as an endpoint.
There is no need to switch to a config.ru simply because you switched to the modular style, and you don’t have to use the modular style for running with a config.ru.
Understand Rack
What is Rack[fn:3]?
Rack is the HTTP interface for Ruby. Rack defines a standard interface for interacting with HTTP and connecting web servers[1]
To get started, all you need is an object that responds to a call method, taking in an environment hash and returning an Array with the HTTP response code, headers, and response body[2]
What is Middleware?
A middleware component sits between the client and the server, processing inbound requests and outbound responses.[3]
Understand Files and Directory
explain the expand_path
this will give you the absolute address of the file
path = File.expand_path("../public", __FILE__)
# => "/home/scipio/index/public"
path = File.expand_path("../public")
# => "/home/scipio/public"
explain the glob
Dir.[]
is the same asDir.glob
. If we want to show all the files include the hidden files, we useDir.entries
. If you don’t want the hidden files, usingDir.glob
.glob
you have to setup the pattern you want. For example, here, we wantALL
the files with*
. if we want all the ruby file, we should use*.rb
rbfiles = File.join("**", "*.rb")
Dir.glob(rbfiles) #=> ["main.rb",
# "lib/song.rb",
# "lib/song/karaoke.rb"]
File.file?
returntrue
if it is a file, and you have to give the absoulute address.File.directory?
will returntrue
, if is directory.File.basename
will return the basename of the file.
Dir.entries(path)
# => ["chp12.txt", "chp1.txt", "chp11.txt", "toc.txt", "..", "chp5.txt", ".", "chp6.txt", "chp10.txt", "chp2.txt", "chp7.txt", "chp9.txt", "chp3.txt", "chp4.txt", "chp8.txt"]
Dir.entries(path).select {|f| !File.directory? f}
# => ["chp12.txt", "chp1.txt", "chp11.txt", "toc.txt", "chp5.txt", "chp6.txt", "chp10.txt", "chp2.txt", "chp7.txt", "chp9.txt", "chp3.txt", "chp4.txt", "chp8.txt"]
Dir[path]
Dir.glob(path + "/*").select {|f| File.file? f}
# => ["/home/scipio/ls-pratice/index/public/chp12.txt", "/home/scipio/ls-pratice/index/public/chp1.txt", "/home/scipio/ls-pratice/index/public/chp11.txt", "/home/scipio/ls-pratice/index/public/toc.txt", "/home/scipio/ls-pratice/index/public/chp5.txt", "/home/scipio/ls-pratice/index/public/chp6.txt", "/home/scipio/ls-pratice/index/public/chp10.txt", "/home/scipio/ls-pratice/index/public/chp2.txt", "/home/scipio/ls-pratice/index/public/chp7.txt", "/home/scipio/ls-pratice/index/public/chp9.txt", "/home/scipio/ls-pratice/index/public/chp3.txt", "/home/scipio/ls-pratice/index/public/chp4.txt", "/home/scipio/ls-pratice/index/public/chp8.txt"]
Dir.glob(path + "/*").select {|f| File.file? f}.map{ |f| File.basename(f) }
# => ["chp12.txt", "chp1.txt", "chp11.txt", "toc.txt", "chp5.txt", "chp6.txt", "chp10.txt", "chp2.txt", "chp7.txt", "chp9.txt", "chp3.txt", "chp4.txt", "chp8.txt"]
[1] http://hawkins.io/2012/07/rack_from_the_beginning/
[2] https://blog.engineyard.com/2015/understanding-rack-apps-and-middleware
[3] https://blog.engineyard.com/2015/understanding-rack-apps-and-middleware