1 Rails 路由器的目的
Rails 路由器根据 URL 路径将传入的 HTTP 请求匹配到 Rails 应用程序中的特定控制器操作。(它也可以转发到 Rack 应用程序。)路由器还会根据在路由器中配置的资源生成路径和 URL 助手。
1.1 将传入的 URL 路由到代码
当您的 Rails 应用程序收到传入请求时,它会要求路由器将其匹配到控制器操作(也称为方法)。例如,考虑以下传入请求
GET /users/17
如果第一个匹配的路由是
get "/users/:id", to: "user#show"
请求将匹配到 UsersController
类的 show
操作,params
哈希中包含 { id: '17' }
。
to:
选项期望传递字符串时使用 controller#action
格式。或者,您可以传递符号并使用 action:
选项而不是 to:
。您也可以传递没有 #
的字符串,在这种情况下,controller:
选项将用于 to:
。例如
get "/users/:id", controller: "users", action: :show
Rails 在指定路由时使用 snake_case 作为控制器名称。例如,如果您有一个名为 UserProfilesController
的控制器,则应将路由指定为 user_profiles#show
。
1.2 从代码生成路径和 URL
路由器会自动为您的应用程序生成路径和 URL 助手方法。使用这些方法,您可以避免硬编码路径和 URL 字符串。
例如,当定义以下路由时,user_path
和 user_url
助手方法可用
get "/users/:id", to: "users#show", as: "user"
as:
选项用于为路由提供自定义名称,该名称在生成 URL 和路径助手时使用。
假设您的应用程序在控制器中包含以下代码
@user = User.find(params[:id])
以及在相应的视图中包含以下内容
<%= link_to 'User Record', user_path(@user) %>
路由器将从 user_path(@user)
生成路径 /users/17
。使用 user_path
助手可以避免在视图中硬编码路径。如果您最终将路由移到另一个 URL,这将非常有用,因为您不需要更新相应的视图。
它还会生成 user_url
,其目的类似。user_path
生成类似于 /users/17
的相对 URL,而 user_url
在上述示例中生成类似于 https://example.com/users/17
的绝对 URL。
1.3 配置 Rails 路由器
路由位于 config/routes.rb
中。以下是一个典型的 Rails 应用程序中路由的示例。以下部分将解释此文件中使用的不同路由助手
Rails.application.routes.draw do
resources :brands, only: [:index, :show] do
resources :products, only: [:index, :show]
end
resource :basket, only: [:show, :update, :destroy]
resolve("Basket") { route_for(:basket) }
end
由于这是一个普通的 Ruby 源文件,因此您可以使用 Ruby 的所有功能(如条件语句和循环)来帮助您定义路由。
包装路由定义的 Rails.application.routes.draw do ... end
块是建立路由器 DSL(特定领域语言)范围所必需的,并且不能删除。
在 routes.rb
中注意变量名称,因为它们可能会与路由器的 DSL 方法冲突。
2 资源路由:Rails 默认值
资源路由允许您快速为给定资源控制器声明所有常见的路由。例如,对 resources
的一次调用会声明 index
、show
、new
、edit
、create
、update
和 destroy
操作所需的所有路由,而无需单独声明每个路由。
2.1 网络上的资源
浏览器通过使用特定 HTTP 动词(例如 GET
、POST
、PATCH
、PUT
和 DELETE
)发出对 URL 的请求来向 Rails 请求页面。每个 HTTP 动词都是对资源执行操作的请求。资源路由将相关请求映射到单个控制器的操作。
当您的 Rails 应用程序收到对以下内容的传入请求时
DELETE /photos/17
它会要求路由器将其映射到控制器操作。如果第一个匹配的路由是
resources :photos
Rails 将把该请求分派给 PhotosController
上的 destroy
操作,params
中包含 { id: '17' }
。
2.2 CRUD、动词和操作
在 Rails 中,资源路由提供了一种将传入请求(HTTP 动词 + URL 的组合)映射到控制器操作的方式。按照惯例,每个操作通常映射到您的数据上的特定 CRUD 操作。路由文件中的单个条目,例如
resources :photos
在您的应用程序中创建了七个不同的路由,所有路由都映射到 PhotosController
操作
HTTP 动词 | 路径 | 控制器#操作 | 用于 |
---|---|---|---|
GET | /photos | photos#index | 显示所有照片的列表 |
GET | /photos/new | photos#new | 返回用于创建新照片的 HTML 表单 |
POST | /photos | photos#create | 创建新照片 |
GET | /photos/:id | photos#show | 显示特定照片 |
GET | /photos/:id/edit | photos#edit | 返回用于编辑照片的 HTML 表单 |
PATCH/PUT | /photos/:id | photos#update | 更新特定照片 |
DELETE | /photos/:id | photos#destroy | 删除特定照片 |
由于路由器使用 HTTP 动词和路径来匹配传入请求,因此四个 URL 可以映射到七个不同的控制器操作。例如,相同的 photos/
路径在动词为 GET
时匹配 photos#index
,而在动词为 POST
时匹配 photos#create
。
routes.rb
文件中的顺序很重要。Rails 路由按照指定的顺序匹配。例如,如果您在 get 'photos/poll'
上面有一个 resources :photos
,那么 resources
行的 show
操作的路由将在 get
行之前匹配。如果您希望 photos/poll
路由首先匹配,则需要将 get
行移到 resources
行的 **上面**。
2.3 路径和 URL 辅助函数
创建资源路由还会将许多辅助函数公开给应用程序中的控制器和视图。
例如,将 resources :photos
添加到路由文件中将生成这些 _path
辅助函数
路径辅助函数 | 返回 URL |
---|---|
photos_path |
/photos |
new_photo_path |
/photos/new |
edit_photo_path(:id) |
/photos/:id/edit` |
photo_path(:id) |
/photos/:id |
传递给路径辅助函数的参数(如上面的 :id
)将传递给生成的 URL,因此 edit_photo_path(10)
将返回 /photos/10/edit
。
这些 _path
辅助函数中的每一个都对应一个 _url
辅助函数(如 photos_url
),它返回在当前主机、端口和路径前缀前添加前缀的相同路径。
在“_path”和“_url”之前使用的前缀是路由名称,可以通过查看 rails routes
命令输出的“prefix”列来识别。要了解更多信息,请参见下面的 列出现有路由。
2.4 同时定义多个资源
如果您需要为多个资源创建路由,可以通过使用单个对 resources
的调用来定义它们,从而节省一些输入时间。
resources :photos, :books, :videos
以上是以下内容的快捷方式
resources :photos
resources :books
resources :videos
2.5 单数资源
有时,您拥有的资源用户期望只有一个(即,没有意义使用 index
操作来列出该资源的所有值)。在这种情况下,您可以使用 resource
(单数)而不是 resources
。
以下资源路由在您的应用程序中创建了六个路由,所有路由都映射到 Geocoders
控制器
resource :geocoder
resolve("Geocoder") { [:geocoder] }
调用 resolve
是必要的,用于通过 记录识别 将 Geocoder
的实例转换为单数路由。
以下是为单数资源创建的所有路由
HTTP 动词 | 路径 | 控制器#操作 | 用于 |
---|---|---|---|
GET | /geocoder/new | geocoders#new | 返回用于创建地理编码器的 HTML 表单 |
POST | /geocoder | geocoders#create | 创建新的地理编码器 |
GET | /geocoder | geocoders#show | 显示唯一的地理编码器资源 |
GET | /geocoder/edit | geocoders#edit | 返回用于编辑地理编码器的 HTML 表单 |
PATCH/PUT | /geocoder | geocoders#update | 更新唯一的地理编码器资源 |
DELETE | /geocoder | geocoders#destroy | 删除地理编码器资源 |
单数资源映射到复数控制器。例如,geocoder
资源映射到 GeocodersController
。
单数资源路由生成这些辅助函数
new_geocoder_path
返回/geocoder/new
edit_geocoder_path
返回/geocoder/edit
geocoder_path
返回/geocoder
与复数资源一样,以 _url
结尾的相同辅助函数还将包含主机、端口和路径前缀。
2.6 控制器命名空间和路由
在大型应用程序中,您可能希望将控制器组组织到命名空间下。例如,您可能在 Admin::
命名空间下有一些控制器,这些控制器位于 app/controllers/admin
目录中。您可以使用 namespace
块对这样的组进行路由
namespace :admin do
resources :articles
end
这将为每个 articles
和 comments
控制器创建一个路由集。对于 Admin::ArticlesController
,Rails 将创建
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /admin/articles | admin/articles#index | admin_articles_path |
GET | /admin/articles/new | admin/articles#new | new_admin_article_path |
POST | /admin/articles | admin/articles#create | admin_articles_path |
GET | /admin/articles/:id | admin/articles#show | admin_article_path(:id) |
GET | /admin/articles/:id/edit | admin/articles#edit | edit_admin_article_path(:id) |
PATCH/PUT | /admin/articles/:id | admin/articles#update | admin_article_path(:id) |
DELETE | /admin/articles/:id | admin/articles#destroy | admin_article_path(:id) |
请注意,在上面的示例中,所有路径都具有 /admin
前缀,这是 namespace
的默认约定。
2.6.1 使用模块
如果您希望将 /articles
(没有前缀 /admin
)路由到 Admin::ArticlesController
,则可以使用 scope
块指定模块
scope module: "admin" do
resources :articles
end
另一种写法
resources :articles, module: "admin"
2.6.2 使用范围
或者,您也可以将 /admin/articles
路由到 ArticlesController
(没有 Admin::
模块前缀)。您可以使用 scope
块指定路径
scope "/admin" do
resources :articles
end
另一种写法
resources :articles, path: "/admin/articles"
对于这些替代方法(路径中没有 /admin
并且模块前缀中没有 Admin::
),命名路由辅助函数与您没有使用 scope
时保持一致。
在最后一种情况下,以下路径映射到 ArticlesController
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /admin/articles | articles#index | articles_path |
GET | /admin/articles/new | articles#new | new_article_path |
POST | /admin/articles | articles#create | articles_path |
GET | /admin/articles/:id | articles#show | article_path(:id) |
GET | /admin/articles/:id/edit | articles#edit | edit_article_path(:id) |
PATCH/PUT | /admin/articles/:id | articles#update | article_path(:id) |
DELETE | /admin/articles/:id | articles#destroy | article_path(:id) |
如果您需要在 namespace
块中使用不同的控制器命名空间,则可以指定绝对控制器路径,例如:get '/foo', to: '/foo#index'
。
2.7 嵌套资源
通常会有逻辑上是其他资源子资源的资源。例如,假设您的应用程序包含以下模型
class Magazine < ApplicationRecord
has_many :ads
end
class Ad < ApplicationRecord
belongs_to :magazine
end
嵌套路由声明允许您在路由中捕获这种关系
resources :magazines do
resources :ads
end
除了杂志的路由之外,此声明还将路由广告到 AdsController
。以下是嵌套 ads
资源的所有路由
HTTP 动词 | 路径 | 控制器#操作 | 用于 |
---|---|---|---|
GET | /magazines/:magazine_id/ads | ads#index | 显示特定杂志的所有广告列表 |
GET | /magazines/:magazine_id/ads/new | ads#new | 返回用于创建属于特定杂志的新广告的 HTML 表单 |
POST | /magazines/:magazine_id/ads | ads#create | 创建属于特定杂志的新广告 |
GET | /magazines/:magazine_id/ads/:id | ads#show | 显示属于特定杂志的特定广告 |
GET | /magazines/:magazine_id/ads/:id/edit | ads#edit | 返回用于编辑属于特定杂志的广告的 HTML 表单 |
PATCH/PUT | /magazines/:magazine_id/ads/:id | ads#update | 更新属于特定杂志的特定广告 |
DELETE | /magazines/:magazine_id/ads/:id | ads#destroy | 删除属于特定杂志的特定广告 |
这还将创建通常的路径和 url 路由辅助函数,例如 magazine_ads_url
和 edit_magazine_ad_path
。由于 ads
资源嵌套在 magazines
下,因此广告 URL 需要杂志。辅助函数可以将 Magazine
的实例作为第一个参数(edit_magazine_ad_path(@magazine, @ad)
)。
2.7.1 嵌套限制
如果您愿意,可以在其他嵌套资源中嵌套资源。例如
resources :publishers do
resources :magazines do
resources :photos
end
end
在上面的示例中,应用程序将识别诸如以下的路径
/publishers/1/magazines/2/photos/3
相应的路由辅助函数将是 publisher_magazine_photo_url
,要求您在所有三个级别上指定对象。如您所见,深度嵌套的资源可能变得过于复杂和难以维护。
一般经验法则是只将资源嵌套 1 级。
2.7.2 浅层嵌套
避免深度嵌套(如上面推荐的)的一种方法是生成在父级范围内作用域的集合操作 - 这样可以了解层次结构,但不要嵌套成员操作。换句话说,只使用最少的信息来构建路由,这些信息足以唯一地标识资源。
“成员”操作是应用于单个资源的操作,需要 ID 来识别它们正在操作的特定资源,例如 show
、edit
等。“集合”操作是作用于资源整个集合的操作,例如 index
。
例如
resources :articles do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
在上面,我们使用 :only
选项,它告诉 Rails 只创建指定的路由。这个想法在描述性路由和深度嵌套之间取得了平衡。通过 :shallow
选项,可以使用简写语法来实现这一点
resources :articles do
resources :comments, shallow: true
end
这将生成与第一个示例完全相同的路由。您也可以在父级资源中指定 :shallow
选项,在这种情况下,所有嵌套资源都将是浅层的
resources :articles, shallow: true do
resources :comments
resources :quotes
end
上面的文章资源将生成以下路由
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /articles/:article_id/comments(.:format) | comments#index | article_comments_path |
POST | /articles/:article_id/comments(.:format) | comments#create | article_comments_path |
GET | /articles/:article_id/comments/new(.:format) | comments#new | new_article_comment_path |
GET | /comments/:id/edit(.:format) | comments#edit | edit_comment_path |
GET | /comments/:id(.:format) | comments#show | comment_path |
PATCH/PUT | /comments/:id(.:format) | comments#update | comment_path |
DELETE | /comments/:id(.:format) | comments#destroy | comment_path |
GET | /articles/:article_id/quotes(.:format) | quotes#index | article_quotes_path |
POST | /articles/:article_id/quotes(.:format) | quotes#create | article_quotes_path |
GET | /articles/:article_id/quotes/new(.:format) | quotes#new | new_article_quote_path |
GET | /quotes/:id/edit(.:format) | quotes#edit | edit_quote_path |
GET | /quotes/:id(.:format) | quotes#show | quote_path |
PATCH/PUT | /quotes/:id(.:format) | quotes#update | quote_path |
DELETE | /quotes/:id(.:format) | quotes#destroy | quote_path |
GET | /articles(.:format) | articles#index | articles_path |
POST | /articles(.:format) | articles#create | articles_path |
GET | /articles/new(.:format) | articles#new | new_article_path |
GET | /articles/:id/edit(.:format) | articles#edit | edit_article_path |
GET | /articles/:id(.:format) | articles#show | article_path |
PATCH/PUT | /articles/:id(.:format) | articles#update | article_path |
DELETE | /articles/:id(.:format) | articles#destroy | article_path |
使用带有块的 shallow
方法可以在其内部创建一个范围,其中所有嵌套都是浅的。这将生成与上一个示例相同的路由。
shallow do
resources :articles do
resources :comments
resources :quotes
end
end
可以使用两个选项与 scope
配合使用来定制浅层路由 - :shallow_path
和 :shallow_prefix
。
shallow_path
选项会将成员路径前缀为给定的参数。
scope shallow_path: "sekret" do
resources :articles do
resources :comments, shallow: true
end
end
这里的 comments 资源将生成以下路由。
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /articles/:article_id/comments(.:format) | comments#index | article_comments_path |
POST | /articles/:article_id/comments(.:format) | comments#create | article_comments_path |
GET | /articles/:article_id/comments/new(.:format) | comments#new | new_article_comment_path |
GET | /sekret/comments/:id/edit(.:format) | comments#edit | edit_comment_path |
GET | /sekret/comments/:id(.:format) | comments#show | comment_path |
PATCH/PUT | /sekret/comments/:id(.:format) | comments#update | comment_path |
DELETE | /sekret/comments/:id(.:format) | comments#destroy | comment_path |
:shallow_prefix
选项将指定参数添加到 _path
和 _url
路由助手。
scope shallow_prefix: "sekret" do
resources :articles do
resources :comments, shallow: true
end
end
这里的 comments 资源将生成以下路由。
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /articles/:article_id/comments(.:format) | comments#index | article_comments_path |
POST | /articles/:article_id/comments(.:format) | comments#create | article_comments_path |
GET | /articles/:article_id/comments/new(.:format) | comments#new | new_article_comment_path |
GET | /comments/:id/edit(.:format) | comments#edit | edit_sekret_comment_path |
GET | /comments/:id(.:format) | comments#show | sekret_comment_path |
PATCH/PUT | /comments/:id(.:format) | comments#update | sekret_comment_path |
DELETE | /comments/:id(.:format) | comments#destroy | sekret_comment_path |
2.8 路由关注点
路由关注点允许您声明可以在其他资源中重复使用的通用路由。要定义一个关注点,请使用 concern
块。
concern :commentable do
resources :comments
end
concern :image_attachable do
resources :images, only: :index
end
这些关注点可以在资源中使用,以避免代码重复并在路由之间共享行为。
resources :messages, concerns: :commentable
resources :articles, concerns: [:commentable, :image_attachable]
以上等同于
resources :messages do
resources :comments
end
resources :articles do
resources :comments
resources :images, only: :index
end
您还可以调用 concerns
在 scope
或 namespace
块中,以获得与上述相同的結果。例如
namespace :messages do
concerns :commentable
end
namespace :articles do
concerns :commentable
concerns :image_attachable
end
2.9 从对象创建路径和 URL
除了使用路由助手之外,Rails 还可以从一组参数创建路径和 URL。例如,假设您有以下路由集。
resources :magazines do
resources :ads
end
在使用 magazine_ad_path
时,您可以传入 Magazine
和 Ad
实例,而不是数字 ID。
<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %>
生成的路径将类似于 /magazines/5/ads/42
。
您还可以使用带有对象数组的 url_for
来获取上面的路径,就像这样
<%= link_to 'Ad details', url_for([@magazine, @ad]) %>
在这种情况下,Rails 将看到 @magazine
是一个 Magazine
,而 @ad
是一个 Ad
,因此将使用 magazine_ad_path
助手。一个更简洁的方式是写 link_to
,只需指定对象而不是完整的 url_for
调用
<%= link_to 'Ad details', [@magazine, @ad] %>
如果您想链接到某个杂志
<%= link_to 'Magazine details', @magazine %>
对于其他操作,您需要将操作名称作为数组的第一个元素插入,例如 edit_magazine_ad_path
<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>
这使您可以将模型实例视为 URL,这是使用资源风格的一个关键优势。
为了能够从诸如 [@magazine, @ad]
之类的对象自动推导出路径和 URL,Rails 使用了来自 ActiveModel::Naming
和 ActiveModel::Conversion
模块的方法。具体而言,@magazine.model_name.route_key
返回 magazines
,而 @magazine.to_param
返回模型 id
的字符串表示。因此,对于对象 [@magazine, @ad]
,生成的路径可能类似于 /magazines/1/ads/42
。
2.10 添加更多 RESTful 路由
您不仅限于 七个路由,它们是 RESTful 路由默认创建的。您可以添加适用于集合或集合中单个成员的其他路由。
以下部分描述了添加成员路由和集合路由。术语 member
指的是作用于单个元素的路由,例如 show
、update
或 destroy
。术语 collection
指的是作用于多个元素或元素集合的路由,例如 index
路由。
2.10.1 添加成员路由
您可以将 member
块添加到资源块中,就像这样
resources :photos do
member do
get "preview"
end
end
传入到 /photos/1/preview
的 GET 请求将路由到 PhotosController
的 preview
操作。资源 ID 值将在 params[:id]
中可用。它还将创建 preview_photo_url
和 preview_photo_path
助手。
在 member
块中,每个路由定义都指定 HTTP 动词(在上面的示例中,get 'preview'
使用 get
)。除了 get
之外,您还可以使用 patch
、put
、post
或 delete
。
如果您没有多个 member
路由,您也可以将 :on
传递给一个路由,从而消除块。
resources :photos do
get "preview", on: :member
end
您也可以省略 :on
选项,这将创建相同的成员路由,只是资源 ID 值将在 params[:photo_id]
中可用,而不是 params[:id]
中。路由助手也将从 preview_photo_url
和 preview_photo_path
重命名为 photo_preview_url
和 photo_preview_path
。
2.10.2 添加集合路由
要向集合添加路由,请使用 collection
块
resources :photos do
collection do
get "search"
end
end
这将使 Rails 能够识别诸如 /photos/search
(带有 GET)的路径,并将路由到 PhotosController
的 search
操作。它还将创建 search_photos_url
和 search_photos_path
路由助手。
就像成员路由一样,您可以将 :on
传递给一个路由
resources :photos do
get "search", on: :collection
end
如果您使用符号作为第一个位置参数来定义附加的资源路由,请注意它不等于使用字符串。符号推断控制器操作,而字符串推断路径。
2.10.3 添加用于其他新建操作的路由
要使用 :on
快捷方式添加一个备用新建操作
resources :comments do
get "preview", on: :new
end
这将使 Rails 能够识别诸如 /comments/new/preview
(带有 GET)的路径,并将路由到 CommentsController
的 preview
操作。它还将创建 preview_new_comment_url
和 preview_new_comment_path
路由助手。
如果您发现自己需要向一个资源路由添加许多额外的操作,那么该停下来问问自己,您是否在掩盖另一个资源的存在。
可以定制 resources
生成的默认路由和助手,有关更多信息,请参阅 定制资源路由部分。
3 非资源路由
除了使用 resources
进行资源路由之外,Rails 还对将任意 URL 路由到操作提供了强大的支持。您不会获得由资源路由自动生成的路由组。相反,您需要在应用程序中分别设置每个路由。
虽然您通常应该使用资源路由,但在有些情况下,非资源路由更合适。如果资源框架不适合,则无需尝试将应用程序的每一部分都强制放入资源框架中。
非资源路由的一个示例用例是将现有的遗留 URL 映射到新的 Rails 操作。
3.1 绑定参数
当您设置一个常规路由时,您提供了一系列符号,Rails 将这些符号映射到传入 HTTP 请求的部分。例如,考虑以下路由
get "photos(/:id)", to: "photos#display"
如果传入的 /photos/1
的 GET
请求由该路由处理,那么结果将是调用 PhotosController
的 display
操作,并将最终参数 "1"
作为 params[:id]
提供。该路由还将将传入的 /photos
请求路由到 PhotosController#display
,因为 :id
是一个可选参数,在上面的示例中用括号表示。
3.2 动态段
您可以在一个常规路由中设置任意数量的动态段。任何段都将作为 params
的一部分提供给操作。如果您设置以下路由
get "photos/:id/:user_id", to: "photos#show"
该路由将响应诸如 /photos/1/2
的路径。params
哈希将为 { controller: 'photos', action: 'show', id: '1', user_id: '2' }。
默认情况下,动态段不接受点 - 这是因为点被用作格式化路由的分隔符。如果您需要在动态段中使用点,请添加一个覆盖此限制的约束 - 例如,id: /[^\/]+/
允许除斜杠以外的任何字符。
3.3 静态段
您可以通过在创建路由时不为段前缀冒号来指定静态段
get "photos/:id/with_user/:user_id", to: "photos#show"
该路由将响应诸如 /photos/1/with_user/2
的路径。在这种情况下,params
将为 { controller: 'photos', action: 'show', id: '1', user_id: '2' }
。
3.4 查询字符串
params
还将包括来自查询字符串的任何参数。例如,使用以下路由
get "photos/:id", to: "photos#show"
传入的 /photos/1?user_id=2
的 GET
请求将像往常一样调度到 PhotosController
类的 show
操作,而 params
哈希将为 { controller: 'photos', action: 'show', id: '1', user_id: '2' }
。
3.5 定义默认参数
您可以通过为 :defaults
选项提供一个哈希来定义路由中的默认值。这甚至适用于您未指定为动态段的参数。例如
get "photos/:id", to: "photos#show", defaults: { format: "jpg" }
Rails 将将 photos/12
匹配到 PhotosController
的 show
操作,并将 params[:format]
设置为 "jpg"
。
您还可以使用 defaults
块来定义多个项目的默认值
defaults format: :json do
resources :photos
resources :articles
end
您不能通过查询参数覆盖默认值 - 这是出于安全原因。唯一可以覆盖的默认值是通过在 URL 路径中进行替换来覆盖动态段。
3.6 命名路由
您可以使用 :as
选项为任何路由指定一个名称,该名称将由 _path
和 _url
助手使用。
get "exit", to: "sessions#destroy", as: :logout
这将创建 logout_path
和 logout_url
作为应用程序中的路由助手。调用 logout_path
将返回 /exit
。
您还可以使用 as
来覆盖由 resources
定义的路由助手名称,方法是在定义资源之前放置一个自定义路由定义,就像这样
get ":username", to: "users#show", as: :user
resources :users
这将定义一个 user_path
助手,该助手将匹配 /:username
(例如 /jane
)。在 UsersController
的 show
操作中,params[:username]
将包含用户的用户名。
3.7 HTTP 动词约束
一般而言,您应该使用 get
、post
、put
、patch
和 delete
方法来将路由约束到特定动词。有一个 match
方法可以使用 :via
选项来匹配多个动词
match "photos", to: "photos#show", via: [:get, :post]
上面的路由匹配 GET 和 POST 请求到 PhotosController
的 show
操作。
您可以使用 via: :all
将所有动词匹配到特定路由
match "photos", to: "photos#show", via: :all
将 GET
和 POST
请求路由到单个操作存在安全隐患。例如,GET
操作不会检查 CSRF 令牌(因此从 GET
请求写入数据库不是一个好主意。有关更多信息,请参见 安全指南)。一般情况下,请避免将所有动词路由到单个操作,除非你有充分的理由。
3.8 段约束
您可以使用 :constraints
选项强制对动态段进行格式化。
get "photos/:id", to: "photos#show", constraints: { id: /[A-Z]\d{5}/ }
上面的路由定义要求 id
长度为 5 个字母数字字符。因此,此路由将匹配诸如 /photos/A12345
之类的路径,但不匹配 /photos/893
。您可以更简洁地以这种方式表达相同的路由。
get "photos/:id", to: "photos#show", id: /[A-Z]\d{5}/
:constraints
选项接受正则表达式(以及任何响应 matches?
方法的对象),但限制是不能使用正则表达式锚点。例如,以下路由将无法正常工作。
get "/:id", to: "articles#show", constraints: { id: /^\d/ }
但是,请注意,您不需要使用锚点,因为所有路由都在开头和结尾处固定。
例如
get "/:id", to: "articles#show", constraints: { id: /\d.+/ }
get "/:username", to: "users#show"
上面的路由将允许共享根命名空间,并且
- 始终以数字开头的路由路径,例如
/1-hello-world
,路由到articles
,其id
值为。 - 从不以数字开头的路由路径,例如
/david
,路由到users
,其username
值为。
3.9 基于请求的约束
您还可以根据 Request 对象 上返回 String
的任何方法来约束路由。
您指定基于请求的约束的方式与您指定段约束的方式相同。例如
get "photos", to: "photos#index", constraints: { subdomain: "admin" }
将匹配具有指向 admin
子域的路径的传入请求。
您还可以使用 constraints
块指定约束
namespace :admin do
constraints subdomain: "admin" do
resources :photos
end
end
将匹配诸如 https://admin.example.com/photos
之类的内容。
请求约束通过在 Request 对象 上调用与哈希键同名的方法,然后将返回值与哈希值进行比较来工作。例如:constraints: { subdomain: 'api' }
将按预期匹配 api
子域。但是,使用符号 constraints: { subdomain: :api }
则不会,因为 request.subdomain
返回 'api'
作为字符串。
约束值应与相应的 Request 对象方法返回值类型匹配。
对于 format
约束有一个例外,虽然它是 Request 对象上的一个方法,但它也是每个路径上的一个隐式可选参数。段约束优先,format
约束仅在通过哈希强制执行时应用。例如,get 'foo', constraints: { format: 'json' }
将匹配 GET /foo
,因为格式默认情况下是可选的。
您可以 使用 lambda(如 get 'foo', constraints: lambda { |req| req.format == :json }
)仅将路由匹配到显式 JSON 请求。
3.10 高级约束
如果您有更高级的约束,您可以提供一个响应 matches?
的对象,Rails 应该使用该对象。假设您想将受限列表中的所有用户路由到 RestrictedListController
。您可以执行以下操作
class RestrictedListConstraint
def initialize
@ips = RestrictedList.retrieve_ips
end
def matches?(request)
@ips.include?(request.remote_ip)
end
end
Rails.application.routes.draw do
get "*path", to: "restricted_list#index",
constraints: RestrictedListConstraint.new
end
您还可以将约束指定为 lambda
Rails.application.routes.draw do
get "*path", to: "restricted_list#index",
constraints: lambda { |request| RestrictedList.retrieve_ips.include?(request.remote_ip) }
end
matches?
方法和 lambda 都将 request
对象作为参数。
3.10.1 块形式的约束
您可以在块形式中指定约束。当您需要将相同的规则应用于多个路由时,这很有用。例如
class RestrictedListConstraint
# ...Same as the example above
end
Rails.application.routes.draw do
constraints(RestrictedListConstraint.new) do
get "*path", to: "restricted_list#index"
get "*other-path", to: "other_restricted_list#index"
end
end
您还可以使用 lambda
Rails.application.routes.draw do
constraints(lambda { |request| RestrictedList.retrieve_ips.include?(request.remote_ip) }) do
get "*path", to: "restricted_list#index"
get "*other-path", to: "other_restricted_list#index"
end
end
3.11 通配符段
路由定义可以包含一个通配符段,它是一个以星号开头的段,例如 *other
get "photos/*other", to: "photos#unknown"
通配符段允许使用称为“路由通配”的功能,这是一种指定将特定参数(上面的 *other
)匹配到路由的剩余部分的方法。
因此,上面的路由将匹配 photos/12
或 /photos/long/path/to/12
,并将 params[:other]
设置为 "12"
或 "long/path/to/12"
。
通配符段可以出现在路由中的任何位置。例如
get "books/*section/:title", to: "books#show"
将匹配 books/some/section/last-words-a-memoir
,其中 params[:section]
等于 'some/section'
,而 params[:title]
等于 'last-words-a-memoir'
。
从技术上讲,一条路由甚至可以包含多个通配符段。匹配器按出现的顺序将段分配给参数。例如
get "*a/foo/*b", to: "test#index"
将匹配 zoo/woo/foo/bar/baz
,其中 params[:a]
等于 'zoo/woo'
,而 params[:b]
等于 'bar/baz'
。
3.12 格式段
给定此路由定义
get "*pages", to: "pages#show"
通过请求 '/foo/bar.json'
,您的 params[:pages]
将等于 'foo/bar'
,请求格式为 JSON,位于 params[:format]
中。
使用 format
的默认行为是,如果包含 Rails 会自动从 URL 中捕获它并将其包含在 params[:format] 中,但 URL 中不需要 format
。
如果您想匹配没有显式格式的 URL 并忽略包含格式扩展名的 URL,您可以提供 format: false
,如下所示
get "*pages", to: "pages#show", format: false
如果您想使格式段变为强制性,以便不能省略它,您可以提供 format: true
,如下所示
get "*pages", to: "pages#show", format: true
3.13 重定向
您可以使用路由器中的 redirect
帮助器将任何路径重定向到任何其他路径
get "/stories", to: redirect("/articles")
您还可以重用匹配中的动态段,以重定向到
get "/stories/:name", to: redirect("/articles/%{name}")
您还可以向 redirect
提供一个块,该块接收符号化的路径参数和请求对象
get "/stories/:name", to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" }
get "/stories", to: redirect { |path_params, req| "/articles/#{req.subdomain}" }
请注意,默认重定向是 301“永久移动”重定向。请记住,某些 Web 浏览器或代理服务器会缓存此类重定向,从而使旧页面无法访问。您可以使用 :status
选项更改响应状态
get "/stories/:name", to: redirect("/articles/%{name}", status: 302)
在所有这些情况下,如果您没有提供主机(http://www.example.com
),Rails 将从当前请求中获取这些详细信息。
3.14 路由到 Rack 应用程序
而不是将 :to
指定为字符串,例如 'articles#index'
(对应于 ArticlesController
类中的 index
方法),您可以将任何 Rack 应用程序 指定为匹配器的端点
match "/application.js", to: MyRackApp, via: :all
只要 MyRackApp
响应 call
并返回 [status, headers, body]
,路由器就不会区分 Rack 应用程序和控制器操作。这是 via: :all
的适当用法,因为您将希望允许您的 Rack 应用程序处理所有动词。
一个有趣的小细节 - 'articles#index'
展开为 ArticlesController.action(:index)
,它返回一个有效的 Rack 应用程序。
由于 proc/lambda 是响应 call
的对象,因此您可以内联实现非常简单的路由(例如,用于运行状况检查),类似于:get '/health', to: ->(env) { [204, {}, ['']] }
如果您将 Rack 应用程序指定为匹配器的端点,请记住,路由在接收应用程序中将保持不变。使用以下路由,您的 Rack 应用程序应该期望路由为 /admin
match "/admin", to: AdminApp, via: :all
如果您希望您的 Rack 应用程序在根路径接收请求,请使用 mount
mount AdminApp, at: "/admin"
3.15 使用 root
您可以使用 root
方法指定 Rails 应该将 '/'
路由到哪里
root to: "pages#main"
root "pages#main" # shortcut for the above
您通常将 root
路由放在文件顶部,以便它可以首先匹配。
root
路由主要处理默认的 GET
请求。但是,可以将其配置为处理其他动词(例如 root "posts#index", via: :post
)
您也可以在命名空间和作用域中使用 root
root to: "home#index"
namespace :admin do
root to: "admin#index"
end
以上将匹配 /admin
到 AdminController
的 index
操作,并将 /
匹配到 HomeController
的 index
操作。
3.16 Unicode 字符路由
您可以直接指定 Unicode 字符路由。例如
get "こんにちは", to: "welcome#index"
3.17 直接路由
您可以通过调用 direct
创建自定义 URL 帮助器。例如
direct :homepage do
"https://rubyonrails.net.cn"
end
# >> homepage_url
# => "https://rubyonrails.net.cn"
块的返回值必须是 url_for
方法的有效参数。因此,您可以传递一个有效的字符串 URL、哈希、数组、Active Model 实例或 Active Model 类。
direct :commentable do |model|
[ model, anchor: model.dom_id ]
end
direct :main do
{ controller: "pages", action: "index", subdomain: "www" }
end
# >> main_url
# => "http://www.example.com/pages"
3.18 使用 resolve
resolve
方法允许自定义模型的多态映射。例如
resource :basket
resolve("Basket") { [:basket] }
<%= form_with model: @basket do |form| %>
<!-- basket form -->
<% end %>
这将生成单数 URL /basket
,而不是通常的 /baskets/:id
。
4 自定义资源路由
虽然 resources
生成的默认路由和帮助器通常会很好地为您服务,但您可能需要以某种方式对其进行自定义。Rails 允许使用多种不同的方法来自定义资源路由和帮助器。本节将详细介绍可用的选项。
4.1 指定要使用的控制器
:controller
选项允许您显式指定要用于资源的控制器。例如
resources :photos, controller: "images"
将识别以 /photos
开头的传入路径,但路由到 Images
控制器
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /photos | images#index | photos_path |
GET | /photos/new | images#new | new_photo_path |
POST | /photos | images#create | photos_path |
GET | /photos/:id | images#show | photo_path(:id) |
GET | /photos/:id/edit | images#edit | edit_photo_path(:id) |
PATCH/PUT | /photos/:id | images#update | photo_path(:id) |
DELETE | /photos/:id | images#destroy | photo_path(:id) |
对于命名空间控制器,您可以使用目录符号。例如
resources :user_permissions, controller: "admin/user_permissions"
这将路由到 Admin::UserPermissionsController
实例。
仅支持目录符号。使用 Ruby 常量符号指定控制器(例如 controller: 'Admin::UserPermissions'
)不受支持。
4.2 指定对 id
的约束
您可以使用 :constraints
选项指定对隐式 id
的必需格式。例如
resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ }
此声明将 :id
参数约束为匹配给定的正则表达式。路由器将不再将 /photos/1
匹配到此路由。相反,/photos/RR27
将匹配。
您可以使用块形式指定要应用于多个路由的单个约束
constraints(id: /[A-Z][A-Z][0-9]+/) do
resources :photos
resources :accounts
end
您也可以在此上下文中使用非资源路由部分中提供的更高级约束。
默认情况下,:id
参数不接受点 - 这是因为点用作格式化路由的分隔符。如果您需要在:id
中使用点,请添加一个覆盖此行为的约束 - 例如,id: /[^\/]+/
允许除斜杠以外的任何字符。
4.3 覆盖命名路由助手
:as
选项允许您覆盖路由助手的默认命名。例如
resources :photos, as: "images"
这将匹配 /photos
并像往常一样将请求路由到 PhotosController
,但使用 :as
选项的值来命名助手 images_path
等,如所示
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /photos | photos#index | images_path |
GET | /photos/new | photos#new | new_image_path |
POST | /photos | photos#create | images_path |
GET | /photos/:id | photos#show | image_path(:id) |
GET | /photos/:id/edit | photos#edit | edit_image_path(:id) |
PATCH/PUT | /photos/:id | photos#update | image_path(:id) |
DELETE | /photos/:id | photos#destroy | image_path(:id) |
4.4 重命名 new
和 edit
路径名称
:path_names
选项允许您覆盖路径中默认的 new
和 edit
段。例如
resources :photos, path_names: { new: "make", edit: "change" }
这将允许使用 /photos/make
和 /photos/1/change
等路径,而不是 /photos/new
和 /photos/1/edit
。
路由助手和控制器操作名称不会受此选项更改。显示的两个路径将具有 new_photo_path
和 edit_photo_path
助手,并且仍然路由到 new
和 edit
操作。
还可以使用 scope
块对所有路由统一更改此选项
scope path_names: { new: "make" } do
# rest of your routes
end
4.5 使用 :as
为命名路由助手添加前缀
您可以使用 :as
选项为 Rails 为路由生成的命名路由助手添加前缀。使用此选项可防止使用路径范围的路由之间的名称冲突。例如
scope "admin" do
resources :photos, as: "admin_photos"
end
resources :photos
这会将 /admin/photos
的路由助手从 photos_path
、new_photos_path
等更改为 admin_photos_path
、new_admin_photo_path
等。如果没有在作用域 resources :photos
上添加 as: 'admin_photos'
,则非作用域 resources :photos
将没有任何路由助手。
要为一组路由助手添加前缀,请将 :as
与 scope
结合使用
scope "admin", as: "admin" do
resources :photos, :accounts
end
resources :photos, :accounts
与以前一样,这会将 /admin
作用域资源助手更改为 admin_photos_path
和 admin_accounts_path
,并允许非作用域资源使用 photos_path
和 accounts_path
。
namespace
作用域将自动添加 :as
以及 :module
和 :path
前缀。
4.6 在嵌套资源中使用 :as
:as
选项也可以覆盖嵌套路由中资源的路由助手名称。例如
resources :magazines do
resources :ads, as: "periodical_ads"
end
这将创建诸如 magazine_periodical_ads_url
和 edit_magazine_periodical_ad_path
之类的路由助手,而不是默认的 magazine_ads_url
和 edit_magazine_ad_path
。
4.7 参数化作用域
您可以使用命名参数为路由添加前缀
scope ":account_id", as: "account", constraints: { account_id: /\d+/ } do
resources :articles
end
这将提供诸如 /1/articles/9
之类的路径,并允许您在控制器、助手和视图中将路径的 account_id
部分引用为 params[:account_id]
。
它还将生成以 account_
为前缀的路径和 URL 助手,您可以像预期的那样将您的对象传递给它们
account_article_path(@account, @article) # => /1/article/9
url_for([@account, @article]) # => /1/article/9
form_with(model: [@account, @article]) # => <form action="/1/article/9" ...>
:as
选项也不是强制性的,但是如果没有它,Rails 在评估 url_for([@account, @article])
或其他依赖 url_for
的助手(例如 form_with
)时会引发错误。
4.8 限制创建的路由
默认情况下,使用 resources
会为七个默认操作(index
、show
、new
、create
、edit
、update
和 destroy
)创建路由。您可以使用 :only
和 :except
选项来限制创建哪些路由。
:only
选项告诉 Rails 只创建指定的路由
resources :photos, only: [:index, :show]
现在,对 /photos
或 /photos/:id
的 GET
请求将成功,但对 /photos
的 POST
请求将无法匹配。
:except
选项指定 Rails 不应创建的路由或路由列表
resources :photos, except: :destroy
在这种情况下,Rails 将创建所有正常的路由,除了 destroy
的路由(对 /photos/:id
的 DELETE
请求)。
如果您的应用程序有许多 RESTful 路由,则使用 :only
和 :except
只生成您实际需要的路由可以减少内存使用,并通过消除未使用的路由 来加快路由过程。
4.9 翻译后的路径
使用 scope
,我们可以更改 resources
生成的路径名称
scope(path_names: { new: "neu", edit: "bearbeiten" }) do
resources :categories, path: "kategorien"
end
Rails 现在创建了到 CategoriesController
的路由。
HTTP 动词 | 路径 | 控制器#操作 | 命名路由辅助函数 |
---|---|---|---|
GET | /kategorien | categories#index | categories_path |
GET | /kategorien/neu | categories#new | new_category_path |
POST | /kategorien | categories#create | categories_path |
GET | /kategorien/:id | categories#show | category_path(:id) |
GET | /kategorien/:id/bearbeiten | categories#edit | edit_category_path(:id) |
PATCH/PUT | /kategorien/:id | categories#update | category_path(:id) |
DELETE | /kategorien/:id | categories#destroy | category_path(:id) |
4.10 指定资源的单数形式
如果需要覆盖资源的单数形式,可以通过 inflections
向 Active Support Inflector 添加规则
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular "tooth", "teeth"
end
4.11 重命名默认路由参数 id
可以使用 :param
选项重命名默认参数名称 id
。例如
resources :videos, param: :identifier
现在将使用 params[:identifier]
而不是 params[:id]
。
videos GET /videos(.:format) videos#index
POST /videos(.:format) videos#create
new_video GET /videos/new(.:format) videos#new
edit_video GET /videos/:identifier/edit(.:format) videos#edit
Video.find_by(id: params[:identifier])
# Instead of
Video.find_by(id: params[:id])
您可以覆盖相关模型的 ActiveRecord::Base#to_param
来构建 URL
class Video < ApplicationRecord
def to_param
identifier
end
end
irb> video = Video.find_by(identifier: "Roman-Holiday")
irb> edit_video_path(video)
=> "/videos/Roman-Holiday/edit"
5 检查路由
Rails 提供了几种不同的方法来检查和测试您的路由。
5.1 列出现有路由
要获取应用程序中所有可用路由的完整列表,请访问 开发环境中的 https://127.0.0.1:3000/rails/info/routes
。您也可以在终端中执行 bin/rails routes
命令以获得相同的输出。
这两种方法都将列出所有路由,顺序与它们在 config/routes.rb
中出现的顺序相同。对于每个路由,您将看到
- 路由名称(如果有)
- 使用的 HTTP 动词(如果路由没有响应所有动词)
- 要匹配的 URL 模式
- 路由的路由参数
例如,以下是 RESTful 路由的 bin/rails routes
输出的一部分
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
路由名称(例如上面的 new_user
)可以被认为是派生路由助手的基础。要获取路由助手的名称,请在路由名称(例如 new_user_path
)中添加后缀 _path
或 _url
。
您还可以使用 --expanded
选项来打开扩展表格格式模式。
$ bin/rails routes --expanded
--[ Route 1 ]----------------------------------------------------
Prefix | users
Verb | GET
URI | /users(.:format)
Controller#Action | users#index
--[ Route 2 ]----------------------------------------------------
Prefix |
Verb | POST
URI | /users(.:format)
Controller#Action | users#create
--[ Route 3 ]----------------------------------------------------
Prefix | new_user
Verb | GET
URI | /users/new(.:format)
Controller#Action | users#new
--[ Route 4 ]----------------------------------------------------
Prefix | edit_user
Verb | GET
URI | /users/:id/edit(.:format)
Controller#Action | users#edit
5.2 搜索路由
您可以使用 grep 选项:-g
搜索您的路由。这将输出任何部分匹配 URL 助手方法名称、HTTP 动词或 URL 路径的路由。
$ bin/rails routes -g new_comment
$ bin/rails routes -g POST
$ bin/rails routes -g admin
如果您只想查看映射到特定控制器的路由,可以使用控制器选项:-c
。
$ bin/rails routes -c users
$ bin/rails routes -c admin/users
$ bin/rails routes -c Comments
$ bin/rails routes -c Articles::CommentsController
如果您将终端窗口放大到输出行不换行,或者使用 --expanded
选项,bin/rails routes
的输出更易于阅读。
5.3 列出未使用的路由
您可以使用 --unused
选项扫描您的应用程序以查找未使用的路由。Rails 中的“未使用”路由是在 config/routes.rb
文件中定义但未被应用程序中的任何控制器操作或视图引用的路由。例如
$ bin/rails routes --unused
Found 8 unused routes:
Prefix Verb URI Pattern Controller#Action
people GET /people(.:format) people#index
POST /people(.:format) people#create
new_person GET /people/new(.:format) people#new
edit_person GET /people/:id/edit(.:format) people#edit
person GET /people/:id(.:format) people#show
PATCH /people/:id(.:format) people#update
PUT /people/:id(.:format) people#update
DELETE /people/:id(.:format) people#destroy
5.4 Rails 控制台中的路由
您可以在 Rails 控制台 中使用 Rails.application.routes.url_helpers
访问路由助手。它们也可以通过 app 对象访问。例如
irb> Rails.application.routes.url_helpers.users_path
=> "/users"
irb> user = User.first
=> #<User:0x00007fc1eab81628
irb> app.edit_user_path(user)
=> "/users/1/edit"
6 测试路由
Rails 提供了三个内置断言,旨在简化路由测试
6.1 assert_generates
断言
assert_generates
断言特定选项集会生成特定路径,并且可以与默认路由或自定义路由一起使用。例如
assert_generates "/photos/1", { controller: "photos", action: "show", id: "1" }
assert_generates "/about", controller: "pages", action: "about"
6.2 assert_recognizes
断言
assert_recognizes
是 assert_generates
的反面。它断言给定路径被识别并将其路由到应用程序中的特定位置。例如
assert_recognizes({ controller: "photos", action: "show", id: "1" }, "/photos/1")
您可以提供一个 :method
参数来指定 HTTP 动词
assert_recognizes({ controller: "photos", action: "create" }, { path: "photos", method: :post })
6.3 assert_routing
断言
assert_routing
断言双向检查路由。它结合了 assert_generates
和 assert_recognizes
的功能。它测试路径是否生成选项,以及选项是否生成路径
assert_routing({ path: "photos", method: :post }, { controller: "photos", action: "create" })
7 使用 draw
分割大型路由文件
在一个具有数千个路由的大型应用程序中,单个 config/routes.rb
文件会变得笨拙且难以阅读。Rails 提供了一种方法,可以使用 draw
宏将单个 routes.rb
文件拆分成多个较小的文件。
例如,您可以添加一个 admin.rb
文件,其中包含与管理区域相关的所有路由,另一个 api.rb
文件用于 API 相关资源等。
# config/routes.rb
Rails.application.routes.draw do
get "foo", to: "foo#bar"
draw(:admin) # Will load another route file located in `config/routes/admin.rb`
end
# config/routes/admin.rb
namespace :admin do
resources :comments
end
在 Rails.application.routes.draw
块本身内部调用 draw(:admin)
将尝试加载一个与给定参数(本例中为 admin.rb
)同名的路由文件。该文件需要位于 config/routes
目录或任何子目录(即 config/routes/admin.rb
或 config/routes/external/admin.rb
)中。
您可以在辅助路由文件(如 admin.rb
)中使用正常的路由 DSL,但不要用 Rails.application.routes.draw
块将其包围。这应该只在主 config/routes.rb
文件中使用。
除非您确实需要此功能,否则请不要使用它。拥有多个路由文件使得在一个地方发现路由变得更加困难。对于大多数应用程序 - 即使是具有数百个路由的应用程序 - 对于开发人员来说,拥有单个路由文件更容易。Rails 路由 DSL 已经提供了一种使用 namespace
和 scope
以有组织的方式划分路由的方法。