iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Modern Web

Rails,我要進來囉系列 第 25

第二十五天:Rack 到底是什麼?跟 Rails 有什麼關係?那 Rake 又是什麼?

  • 分享至 

  • xImage
  •  

開場白

鼬~~哩賀,我是寫程式的山姆老弟,昨天跟大家一起看了 Rails 有哪些可以客製化的設定,今天來看看 RailsGuide 的 Rack 篇,了解一下 Rack 這個在 Rails 時不時就會出現的東東,夠夠~

https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day25-1.png

Rack 是什麼?

Rack 是一個 ruby gem,負責以極簡的方式處理 HTTP requests, responses,可以完全獨立於 Rails 之外運行,

最簡單的 Rack Hello World

我們先試試看使用最純粹的 Rack,也就是沒有 Rails 包裝過的 Rack,假設我在 ~/Downloads 新增一個 config.ru 的檔案,內容如下

# ~/Downloads/config.ru
require 'rack'

class HelloWorld
  def call(env)
    [200, {"Content-Type" => "text/plain"}, ["Hello world, Rack!"]]
  end
end

run HelloWorld.new

使用方式:$ rackup 啟動,預設是開在 9292 port

Puma starting in single mode...
* Puma version: 5.6.5 (ruby 3.0.0-p0) ("Birdie's Version")
*  Min threads: 0
*  Max threads: 5
*  Environment: development
*          PID: 88707
* Listening on http://127.0.0.1:9292
* Listening on http://[::1]:9292
Use Ctrl-C to stop

這時候去 127.0.0.1:9292 看,就可以看到我們的 Hello World

https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day25-2.png

Rack 和 Rails 是什麼關係?

Rack 是一個把 web server(Nginx, Apache, …) 和 web framework(Rails, …) 串起來的角色

Rails 是怎麼使用 Rack 的?

創立新的 Rails 專案的時候,Rails 就會在專案根目錄裡,自動創建 config.ru 檔案,像下面這樣,看起來是不是跟上面的 Rack Hello World 有點像,有個 run 去啟動

# config.ru

# This file is used by Rack-based servers to start the application.

require_relative "config/environment"

run Rails.application
Rails.application.load_server

當你執行 $ rails server 時,其實就是創建一個 Rails::Server 的 instance,這個 Rails::Server 其實也就是繼承 Rack::Server,有興趣可以去 Rails 的 source code 看一下,我把最直接相關的部分截出來:

# rails/railties/lib/rails/commands/server/server_command.rb
module Rails
	class Server < ::Rack::Server
		...
		def start(...)
			trap(:INT) { exit }
      create_tmp_directories
      setup_dev_caching
      log_to_stdout if options[:log_stdout]
			super()
		end
		...
	end
end

以上 start() method 做的事情,其實不難理解

  1. trap(:INT) { exit } ,抓 SYSINT signal,當你在終端機按下 Ctrl+C 會送出 SYSINT 的訊號,如果抓到這個 signal,就 exit,跳出 rails server 的運行
  2. create_tmp_directories,就是在 Rails 專案目錄底下的 tmp/ 資料夾和底下的 pids, cache, sockets 的預設資料夾
  3. setup_dev_caching,就是如果是 development 環境,就會啟動 DevCache,這根據預設設定 加上 我們在環境檔裡面的設定,來決定這個 cache 行為
  4. log_to_stdout,就是把 log 印出到終端機,而不是寫入到檔案
  5. super(),去執行 Rack::Server 原本該執行的啟動程序

除了上面 Rails 對 Rack 的用法,Rack 在 Rails 中還扮演了其他重要的角色,就是 Rails 的各種 Middleware

我們沿用前天的專案,用 $ rails middleware 可以查看目前專案用的 middleware 有哪些

https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day25-3.png

在其中可以看到很多 Rack 的身影,主要是因為 Rack 的特性,Rack 作為 middleware 可以對 request 進行前處理,處理後再交由下一層的 middleware 繼續處理,就這樣一層一層處理到最後再交由 Controller 的 action,所以 middleware 的順序是有意義的,如果有要自己開發 middleware 的話需要注意

Rake 又是什麼東東?

Rake 也是一個 Ruby 的 gem,現在已經被包在 ruby 裡了,像是 C 語言的 Makefile,負責執行打包(Build)任務,但其實不限定打包,只要是 ruby 能寫的,都能用 Rake 執行

我們試著寫一個最簡單的 Rake hello world,在 ~/Downloads 新增一個叫做 Rakefile 的檔案

# ~/Downloads/Rakefile

task :hello do
	puts("Hello world, Rake!")
end

然後可以在 ~/Downloads 執行 $ rake hello

https://raw.githubusercontent.com/shrimp509/my-img-host/master/relacs-studio/Rails%E6%88%91%E8%A6%81%E9%80%B2%E4%BE%86%E5%9B%89/day25-4.png

你可以在一個 Rakefile 中定義很多個 tasks,也可以定義一個叫做 :default 的 task,那在執行 rake 的時候,不指定 task 的時候就會去執行 default 的任務

簡單來說,RackRake 是兩個完全沒關係的 gem,只是字面上長得很像,同時又被 Rails 拿來用而已

總結

今天總算是有搞懂 RackRake 的差別,也有稍微看了下 Rails 是怎麼使用 Rack 的,才知道原來 Rack 的重要性

今天就先這樣囉,我們明天見~


上一篇
第二十四天:Rails 的各種神奇設定 - Rails Configuration
下一篇
第二十六天:Rails 的 Caching
系列文
Rails,我要進來囉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言