---
# System prepended metadata

title: Rails Guides
tags: [Rails Guides]

---

---
title: Rails Guides
description: Ruby on Rails 官方指南
tags: Rails Guides
---

[Rails Guides](/XS5U4U9XQ5WSg4kYklEajQ)
===
Ruby on Rails Guides (v6.1.4)
These are the new guides for Rails 6.1 based on v6.1.4. These guides are designed to make you immediately productive with Rails, and to help you understand how all of the pieces fit together.

The guides for earlier releases: Rails 6.0, Rails 5.2, Rails 5.1, Rails 5.0, Rails 4.2, Rails 4.1, Rails 4.0, Rails 3.2, Rails 3.1, Rails 3.0, and Rails 2.3.

## [Rails Internationalization (I18n) API](/0PUd3sHXSMi7Sh8DROL8Yg)

## [Rails on Rack](/V1XyMhOnT0698C-y1gyl7g)

本篇介紹 Rails 與 Rack 的整合、如何與其他 Rack 組件互動。

:heavy_check_mark: 如何在 Rails 中使用 Rack [Middleware](https://ithelp.ithome.com.tw/articles/10203041)
:heavy_check_mark: Action Pack 的內部 Middleware stack
:heavy_check_mark: 如何自定 Middleware stack

:::danger
本指南假定您已經了解 Rack 協定和相關概念，例如 middleware、URL maps 和 `Rack::Builder`
:::

## [1. Rack 介紹](https://guides.rubyonrails.org/rails_on_rack.html#introduction-to-rack)

Rack 為使用 Ruby 開發的網路應用程序提供了一個最小化、模組化和容易介接的介面(interface)。
Rack 將 HTTP requests 和 responses 包裝成最簡單的形式，它替 Web servers、Web 框架和兩者之間的軟體(也就是 middleware)所使用的 API，統一並提取為單一個方法來調用。

更多內容請參考：[Rack API 文件](https://rack.github.io/)

解釋 Rack 的運作原理並不在此章節的範圍中，若您對基礎的 Rack 知識還並不熟悉，請先參考[線上資源](#4-線上資源)。

## [2. Rails on Rack](https://guides.rubyonrails.org/rails_on_rack.html#rails-on-rack)

### [2.1 Rails Application's Rack Object](https://guides.rubyonrails.org/rails_on_rack.html#rails-application-s-rack-object)
`Rails.application` 是 Rails application 中主要的 Rack application object。
任何符合 Rack 規範的 web server 都應該使用 `Rails.application` object 來執行 Rails application。

### [2.2 bin/rails server](https://guides.rubyonrails.org/rails_on_rack.html#bin-rails-server)
`bin/rails server` 做最基本的工作，建立一個 `Rack::Server` object 並開啟 web server

`bin/rails server` 如何建立 `Rack::Server` 實體：
```ruby
Rails::Server.new.tap do |server|
  require APP_PATH
  Dir.chdir(Rails.application.root)
  server.start
end
```

`Rails::Server` 繼承自 `Rack::Server` 並且呼叫 `Rack::Server#start` 方法：
```ruby
class Server < ::Rack::Server
  def start
    # ...
    super
  end
end
```

### [2.3 rackup](https://guides.rubyonrails.org/rails_on_rack.html#rackup)
要以 `rackup` 取代 `bin/rails server`，您可以將下方的程式碼放進 Rails application 根目錄內的 `config.ru`：
```ruby
# Rails.root/config.ru
require_relative "config/environment"
run Rails.application
```

開啟 server：
```bash
$ rackup config.ru
```

獲得更多 `rackup` 選項：
```bash
$ rackup --help
```

### [2.4 開發與自動重新加載](https://guides.rubyonrails.org/rails_on_rack.html#development-and-auto-reloading)
Middleware 只會加載一次，並且不會監控更動。
您必須重新啟動 server 才能將更動反映在運行的應用程序中。

## [3. Action Dispatcher Middleware Stack](https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack)
許多 Action Dispatcher 的內部組件是以 Rack middleware 實作的。
`Rails::Application` 使用 `ActionDispatch::MiddlewareStack` 將各種內外部 middlewares 組合起來，形成一個完整的 Rails Rack application。

:::warning
`ActionDispatch::MiddlewareStack` 等同於 Rails 的 `Rack::Builder`，但它的構建是為了更好的靈活性和更多的特性來滿足 Rails 的需求。
:::

### [3.1 Inspecting Middleware Stack](https://guides.rubyonrails.org/rails_on_rack.html#inspecting-middleware-stack)
Rails 有一個方便的命令可用來檢視使用中的 middleware stack：
```bash
$ bin/rails middleware
```

對於新生成的 Rails application，可能會有如下結果：
```ruby
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Sprockets::Rails::QuietAssets
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use WebConsole::Middleware
use ActionDispatch::DebugExceptions
use ActionDispatch::ActionableExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
run MyApp::Application.routes
```
此處顯示的預設 middlewares (包含其他)，均在下面的 [Internal Middlewares](#33-內部-Middleware-Stack) 部分進行總結。

### [3.2 設置 Middleware Stack](https://guides.rubyonrails.org/rails_on_rack.html#configuring-middleware-stack)
Rails 提供了一個簡單的配置介面(configaration interface) `config.middleware`，其透過 `application.rb` 或環境配置檔案 `environment/<environment>.rb`，來添加、刪除和修改在 middleware stack 中的 middlewares。

#### [3.2.1 添加 Middleware](https://guides.rubyonrails.org/rails_on_rack.html#adding-a-middleware)
您可使用以下方法來將新的 middleware 添加至 middleware stack 中：
- `config.middleware.use(new_middleware, args)`
  將新的 middleware 添加至 middleware statck 最尾端。
- `config.middleware.insert_before(existing_middleware, new_middleware, args)`
  將新的 middleware 添加至指定 middleware 的前方。
- `config.middleware.insert_after(existing_middleware, new_middleware, args)`
  將新的 middleware 添加至指定 middleware 的後方。
```ruby=!
# config/application.rb

# Push Rack::BounceFavicon at the bottom
config.middleware.use Rack::BounceFavicon

# Add Lifo::Cache after ActionDispatch::Executor.
# Pass { page_cache: false } argument to Lifo::Cache.
config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false
```

#### [3.2.2 替換 Middleware](https://guides.rubyonrails.org/rails_on_rack.html#swapping-a-middleware)
您可使用 `config.middleware.swap` 來替換 middleware stack 中存在的 middleware。
```ruby
# config/application.rb

# Replace ActionDispatch::ShowExceptions with Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
```

#### [3.2.3 刪除 Middleware](https://guides.rubyonrails.org/rails_on_rack.html#deleting-a-middleware)
將下方的程式碼添加至您的設置當中：
```ruby
# config/application.rb
config.middleware.delete Rack::Runtime
```
現在您可以檢視 middleware stack，您會發現 `Rack::Runtime` 並不在其中：
```bash
$ bin/rails middleware
(in /Users/lifo/Rails/blog)
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
...
run Rails.application.routes
```
若您想要移除與 session 相關的 middleware，請參考下方程式碼：
```ruby
# config/application.rb
config.middleware.delete ActionDispatch::Cookies
config.middleware.delete ActionDispatch::Session::CookieStore
config.middleware.delete ActionDispatch::Flash
```
以及移除瀏覽器相關的 middleware：
```ruby
# config/application.rb
config.middleware.delete Rack::MethodOverride
```

### [3.3 內部 Middleware Stack](https://guides.rubyonrails.org/rails_on_rack.html#internal-middleware-stack)
Action Controller 中的大部分功能都是經由 middlewares 實作的。
下方列表解釋了它們中的每一個的目的：

`Rack::Sendfile`
- 設置 server 特定的 X-Sendfile header。
  透過 `config.action_dispatch.x_sendfile_header` 選項設置。

`ActionDispatch::Static`
- 用於從公共目錄中提供靜態文件。
  如果 `config.public_file_server.enabled` 為 `false`，則禁用。

`Rack::Lock`
- 將 `env["rack.multithread"]` 設置為 `false`，並將 application 包裝在互斥鎖(Mutex)中。

`ActionDispatch::Executor`
- 用於開發期間執行緒安全(thread safe)的重新加載程式碼。

`ActiveSupport::Cache::Strategy::LocalCache::Middleware`
- 用於記憶緩存(cache)。此緩存不是執行緒安全的。

`Rack::Runtime`
- 設置 X-Runtime header，其中包含執行 reqeust 時所用的時間(以秒為單位)。

`Rack::MethodOverride`
- 如果設置了 `params[:_method]`，則允許覆蓋該方法。
  該 middleware 這是支援 PUT 和 DELETE HTTP 方法。

`ActionDispatch::RequestId`
- 為 response 提供唯一的 `X-Request-Id` header，用於啟用 `ActionDispatch::Request#request_id` 方法。

`ActionDispatch::RemoteIp`
- 檢查 IP 詐騙(spoofing)攻擊。

`Sprockets::Rails::QuietAssets`
- 禁止輸出 asset requests 的 logger。

`Rails::Rack::Logger`
- 通知 logs request 已經開始。
  request 完成後，刷新所有 logs。

`ActionDispatch::ShowExceptions`
- rescue 任何 application 回傳的 exception，並且呼叫以最終用戶的格式包裝的 exceptions app。

`ActionDispatch::DebugExceptions`
- 負責記錄 exceptions，如果 request 來自本機，則顯示 debugging 頁面。

`ActionDispatch::ActionableExceptions`
- 提供一種從 Rails 錯誤頁面調度操作(dispatch actions)的方法

`ActionDispatch::Reloader`
- 提供準備和清理 callback，旨在開發期間幫助重新加載程式碼。

`ActionDispatch::Callbacks`
- 提供要在分派 request 前後執行的 callback。

`ActiveRecord::Migration::CheckPending`
- 檢查 pending migrations 並在有任何 migrations 處在 pending 狀態時 raise `ActiveRecord::PendingMigrationError`。

`ActionDispatch::Cookies`
- 為 reqeust 設置 cookies。

`ActionDispatch::Session::CookieStore`
- 負責將 session 存儲在 cookie 中。

`ActionDispatch::Flash`
- 設置 flash keys。只有在 `config.action_controller.session_store` 設置被設定為 value 時才可使用。

`ActionDispatch::ContentSecurityPolicy::Middleware`
- 提供 DSL 以配置 Content-Security-Policy header。

`Rack::Head`
- 將 HEAD requests 轉換為 `GET` requests 並為它們提供服務。

`Rack::ConditionalGet`
- 添加對 "Conditional `GET`" 的支援，以便在頁面未改動時 server 不會回應任何內容。

`Rack::ETag`
- 在所有字串上添加 ETag header。 ETag 用於驗證緩存(cache)。

`Rack::TempfileReaper`
- 清理用於緩衝多部分請求(buffer multipart requests)的臨時檔案(tempfiles)。

:::info
可以在您自定義的 Rack stack 中任意使用上述 middlewares。
:::

## [4. 線上資源](https://guides.rubyonrails.org/rails_on_rack.html#resources)

### [4.1 Learning Rack](https://guides.rubyonrails.org/rails_on_rack.html#learning-rack)
- [Official Rack Website](https://rack.github.io/)
- [Introducing Rack](http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html)

### [4.2 Understanding Middlewares](https://guides.rubyonrails.org/rails_on_rack.html#understanding-middlewares)
- [Railscast on Rack Middlewares](http://railscasts.com/episodes/151-rack-middleware)
