路由模組提供 Ruby 中的 URL 改寫。這是將傳入的請求重新導向至控制器和動作的一種方式。這麼一來便可取代 mod_rewrite 規則。最棒的是,Rails 的 Routing
可搭配任何網路伺服器使用。路由會定義在 config/routes.rb
中。
可以將建立路由想成是替請求繪製一張地圖。地圖會根據某些預先定義的模式告訴請求前往哪裡。
Rails.application.routes.draw do
Pattern 1 tells some request to go to one place
Pattern 2 tell them to go to another
...
end
下列符號為特殊符號
:controller maps to your controller name
:action maps to an action with your controllers
其他名稱只會個別對應至參數,就像 :id
。
資源
資源路由可讓您快速宣告給定資源控制器的所有常見路由。資源路由會在一行 code 中宣告路由,而不是為 index
、show
、new
、edit
、create
、update
和 destroy
動作宣告個別的路由。
resources :photos
有時,您擁有某個資源,而使用者總是不參照 ID 即可查詢該資源。常見範例是 /profile 總是會顯示目前登入使用者的個人資料。此種情況下,您可以使用單數資源來將 /profile(而不是 /profile/:id)對應至顯示動作。
resource :profile
資源通常會是其他資源的邏輯子項。
resources :magazines do
resources :ads
end
您可能希望將控制器群組整理在命名空間中。最常見的情況是,您可能會將多個管理控制器群組在 admin
命名空間中。您會將這些控制器放置在 app/controllers/admin
目錄中,而且可以將它們在路由器中群組在一起。
namespace "admin" do
resources :posts, :comments
end
或者,您可以使用 scope
在不使用個別目錄的情況下,將前置詞新增至路徑。scope
會採用其他選項,而這些選項套用於所有內含路由。
scope path: "/cpanel", as: 'admin' do
resources :posts, :comments
end
詳細資訊請參閱 Routing::Mapper::Resources#resources
、Routing::Mapper::Scoping#namespace
和 Routing::Mapper::Scoping#scope
。
非資源路由
對於與 resources
架構不符的路由,您可以使用 HTTP 輔助方法 get
、post
、patch
、put
和 delete
。
get 'post/:id', to: 'posts#show'
post 'post/:id', to: 'posts#create_comment'
現在,如果您對 /posts/:id
發出 POST 請求,系統將路由至 create_comment
動作。對同個 URL 發出 GET 請求將會路由至 show
動作。
如果您的路由需要回應多種 HTTP 方法(或所有方法),那麼在 match
上使用 :via
選項會比較好。
match 'post/:id', to: 'posts#show', via: [:get, :post]
命名路由
可以透過傳遞 :as
選項來命名路由,讓您可以在來源中輕鬆參照 name_of_route_url
(完整 URL)和 name_of_route_path
(URI 路徑)。
範例
# In config/routes.rb
get '/login', to: 'accounts#login', as: 'login'
# With render, redirect_to, tests, etc.
redirect_to login_url
也可以傳遞引數。
redirect_to show_item_path(id: 25)
使用 root
作為縮寫來為根路徑 “/” 命名路由。
# In config/routes.rb
root to: 'blogs#index'
# would recognize http://www.example.com/ as
params = { controller: 'blogs', action: 'index' }
# and provide these named routes
root_url # => 'http://www.example.com/'
root_path # => '/'
注意:在使用 controller
時,路由只會根據您呼叫區塊參數中的方法,而不是 map 來命名。
# In config/routes.rb
controller :blog do
get 'blog/show' => :list
get 'blog/delete' => :delete
get 'blog/edit' => :edit
end
# provides named routes for show, delete, and edit
link_to @article.title, blog_show_path(id: @article.id)
美化 URL
路由可以產生美化過的 URL。例如
get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: {
year: /\d{4}/,
month: /\d{1,2}/,
day: /\d{1,2}/
}
使用上述路由,URL “localhost:3000/articles/2005/11/06” 會對應至
params = {year: '2005', month: '11', day: '06'}
正規表示法和參數
您可以指定正規表示式來定義參數的格式。
controller 'geocode' do
get 'geocode/:postalcode', to: :show, constraints: {
postalcode: /\d{5}(-\d{4})?/
}
end
約束可以包含『忽略大小寫』和『延伸語法』正規表示式修改詞。
controller 'geocode' do
get 'geocode/:postalcode', to: :show, constraints: {
postalcode: /hx\d\d\s\d[a-z]{2}/i
}
end
controller 'geocode' do
get 'geocode/:postalcode', to: :show, constraints: {
postalcode: /# Postalcode format
\d{5} #Prefix
(-\d{4})? #Suffix
/x
}
end
使用多行修改詞將產生ArgumentError
。編碼正規表示式修改詞會被自動忽略。比對將始終使用預設編碼或 ASCII。
外部重新導向
您可以使用路由器中的重新導向輔助函數將任何路徑重新導向至另一條路徑。
get "/stories", to: redirect("/posts")
Unicode 字元路由
您可以在路由器中指定 Unicode 字元路由。
get "こんにちは", to: "welcome#index"
Routing
to Rack Applications
您不一定要指定 String
(例如對應 PostsController 中索引動作的 posts#index
),而是可以指定任何 Rack 應用程式做為比對器的端點。
get "/application.js", to: Sprockets
重新載入路由
如果您覺得有必要,您可以重新載入路由。
Rails.application.reload_routes!
如果檔案已自上次載入以來經過修改,這將清除所有已命名路由並重新載入 config/routes.rb。若要強制重新載入,請使用 reload!
。
測試路由
兩個用於測試路由的主要方法
assert_routing
def test_movie_route_properly_splits
opts = {controller: "plugin", action: "checkout", id: "2"}
assert_routing "plugin/checkout/2", opts
end
assert_routing
讓您可以測試路由是否正確解析成選項。
assert_recognizes
def test_route_has_options
opts = {controller: "plugin", action: "show", id: "12"}
assert_recognizes opts, "/plugins/show/12"
end
請注意兩者之間的細微差異:assert_routing
測試 URL 是否符合選項,而 assert_recognizes
測試 URL 是否正確解析成參數。
在測試中,您可以僅將 URL 或已命名路由傳遞給 get
或 post
。
def send_to_jail
get '/jail'
assert_response :success
end
def goes_to_login
get login_url
#...
end
檢視所有路由的清單
$ bin/rails routes
使用 -c
指定特定控制器,或使用 -g
grep 路由。在與顯示路由垂直顯示的 --expanded
搭配使用時非常實用。
- 模組 ActionDispatch::Routing::ConsoleFormatter
- 模組 ActionDispatch::Routing::PolymorphicRoutes
- 模組 ActionDispatch::Routing::Redirection
- 模組 ActionDispatch::Routing::UrlFor
- 類別 ActionDispatch::Routing::HtmlTableFormatter
- 類別 ActionDispatch::Routing::Mapper
- 類別 ActionDispatch::Routing::PathRedirect
- 類別 ActionDispatch::Routing::RouteSet