路由模块以原生 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'
现在,如果您 POST 到 /posts/:id,它将路由到 create_comment 操作。同一个 URL 的 GET 请求将路由到 show 操作。
如果您的路由需要响应多个 HTTP 方法(或所有方法),那么在 match 上使用 :via 选项是更优的选择。
match 'post/:id', to: 'posts#show', via: [:get, :post]
命名路由¶ ↑
可以通过传递 :as 选项来命名路由,以便在您的源代码中轻松引用,对于完整 URL 为 name_of_route_url,对于 URI 路径为 name_of_route_path。
示例
# 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
约束可以包括“忽略大小写”和“扩展语法”正则表达式修饰符。
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 应用程序¶ ↑
而不是像 posts#index 这样的 String(对应于 PostsController 中的 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