路由模块提供原生 Ruby 中的 URL 重写。这是一种将传入请求重定向到控制器和操作的方法。它取代了 mod_rewrite 规则。最重要的是,Rails 的 Routing
可与任何 Web 服务器配合使用。路由在 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
。
资源
资源路由允许您快速声明给定资源控制器的所有常用路由。与其分别声明 index
、show
、new
、edit
、create
、update
和 destroy
操作的路由,资源路由在一行代码中声明了它们。
resources :photos
有时,您有一个资源,客户端总是会查找它,而无需引用 ID。一个常见的例子是,/profile 始终显示当前登录用户的个人资料。在这种情况下,您可以使用单数资源将 /profile(而不是 /profile/:id)映射到 show 操作。
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
时,路由只是根据您在块参数上调用的方法命名,而不是映射。
# 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
约束可以包含“ignorecase”和“extended syntax”正则表达式修饰符。
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。
外部重定向
您可以使用路由器中的 redirect 助手将任何路径重定向到另一个路径。
get "/stories", to: redirect("/posts")
Unicode 字符路由
您可以在路由器中指定 Unicode 字符路由。
get "こんにちは", to: "welcome#index"
Routing
到 Rack 应用程序
您可以指定任何 Rack 应用程序作为匹配器的端点,而不是像 posts#index
这样的 String
,它对应于 PostsController 中的 index 操作。
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
查找路由。与 --expanded
结合使用很有用,--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