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
httpis scheme, a protocolwww.example.comis host88is port/homeis the path?item=bookisquery 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/erubiswill 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
&blockandyield
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
argumentto 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
partitionmethod:
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
YAMLobject, 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.globyou have to setup the pattern you want. For example, here, we wantALLthe 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?returntrueif it is a file, and you have to give the absoulute address.File.directory?will returntrue, if is directory.File.basenamewill 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