We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
一行代码完成资源资源路由声明:
resources :photos
这会创建7个不同的路由,这些路由会映射到 Photos 控制器上。
Photos
这样4个URL地址就会映射到7个不同的控制器动作上。
在创建资源路由时,会同时创建多个可以在控制器中使用的辅助方法,如上面的资源路由会创建以下方法:
photos_path:返回值为 /photos
photos_path
new_photos_path:返回值为 /photos/new
new_photos_path
edit_photo_path(:id):返回值为 /photos/:id/edit
edit_photo_path(:id)
photo_path(:id):返回值为 /photos/:id
photo_path(:id)
这些方法都有对应的_url形式(photos_url),前者返回的是路径,后者返回的是完整的url地址。
可以同时定义多个资源路由:
resources :photos, :books, :videos
等价于:
resources :photos resources :books resources :videos
使用 resource 方法可以创建单数资源,这会创建6个不同的路由:
resource
有时候在复数资源中希望能够不使用ID就能查找资源,如显示当前登录用户的信息:
get 'profile', to: 'users#show'
如果 get 方法的to选项的值是字符串,那么这个字符串应该使用controller#action形式,如果是表示动作的符号,则还需要添加controller选项:
get
get 'profile', to: :show, controller: 'users'
把控制器放入同一命名空间是非常常见的,如将管理员有关的控制器置于 Admin:: 命名空间中,这样可以把控制器文件放在 app/controllers/admin 文件夹中,在路由中这样声明:
Admin::
app/controllers/admin
namespace :admin do resources :articles, :comments end
对于articles资源
如果想把 /articles 路径(不带/admin前缀)映射到Admin::Articles控制器上,可以这样声明:
scope module: 'admin' do resources :articles, :comments end
或者
resources :articles, module: 'admin' resources :articles, module: 'admin'
或者:
resources :articles, path: '/admin/articles'
有些资源是其他资源的子资源,这种情况非常常见:
class Magazine < ApplicationRecord has_many :ads end class Ad < ApplicationRecord belongs_to :magazine end
通过嵌套路由来反映模型关联:
resources :magazine do resources :ads end
对于嵌套路由,可以不断嵌套:
resources :publishers do resources :magazine do resources :photos end end
但是显然嵌套太深是非常麻烦的,经验告诉我们嵌套资源层级不应该超过一层,而避免嵌套过深的方法之一就是把动作集合放在父资源中,这样既可以表明层级关系,又不必嵌套成员动作:
resources :articles do resources :comments, only: [:index, :new, :create] end resources :comments, only: [:show, :edit, :update, :destroy]
当然,使用 :shallow 选项可以简化上面的代码:
:shallow
resources :articles do resources :comments, shallow: true end
当然,在复选项中使用 :shallow 选项,这样会在所有的子资源中使用 :shallow 选项:
resources :articles, shallow: true do resources :comments resources :quotes end
也可以使用 shallow 方法创建作用域,使得所有嵌套均为浅层嵌套:
shallow
shallow do resources :articles do resources :comments resources :quotes resources :drafts end end
使用scope方法也可以来定义浅层路由,且有两个选项,:shallow_path 选项会为成员路径添加前缀:
:shallow_path
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
:shallow_prefix 选项会为具名方法添加指定前缀:
:shallow_prefix
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
路由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
除了使用路由辅助方法,Rails还可以从参数数组创建路径和URL地址,假如有以下路由:
使用 magazine_ad_path 方法时,可以传入Magazine和Ad的实例,而不只是数字ID:
magazine_ad_path
<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %>
还可以使用 url_for 方法时传入一组对象,Rails会自动确定对应的路由:
url_for
<%= link_to 'Ad details', url_for([@magazine, @ad]) %>
Rails能够识别各个实例,自动使用 magazine_ad_path 辅助方法。当然在使用 link_to 等辅助方法时,可以只指定对象,而不必完整调用 url_for 方法:
link_to
<%= link_to 'Ad details', [@magazine, @ad] %>
<%= link_to 'Magazine details', @magazine %>
如果想要链接到其他控制器动作,只需把动作名称作为第一个元素插入对象数组即可:
<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>
这样就可把模型实例看做URL地址,这是使用资源式风格最关键的优势之一。
和资源路由自动生成一系列路由不同,这时需要分别声明各个路由,非资源路由可以把任意URL地址映射到控制器动作的路由。
声明普通路由时,可以使用符号作为参数:
get 'photos(/:id)', to: :display
在处理 /photos/1 请求时,会把请求映射到 Photos 控制器的 display 动作上,并把参数1传入params[:id],并将路由映射到 PhotosController#display 上,并且 /photos 请求也会映射到这个控制器动作上,因为 :id 在括号中,是可选参数。
声明普通路由时,允许使用多个动态片段,动态片段会传入params,以便在控制器动作中使用:
get 'photos/:id/:user_id', to: 'photos#show'
/photos/1/2 请求会被映射到 photos#show 动作上,这时 params[:id] 的值是 1 ,params[:user_id] 的值是 2
params 也包含了查询字符串中的所有参数,如:
get 'photos/:id', to: 'photos#show'
/photos/1?user_id=2 请求也会映射到 Photos#show 控制器动作上,这时params的值是
{controller: 'photos', action: 'show', id: '1', user_id: '2'}
:defaults 选项设定的散列为路由定义默认值,未通过动态片段定义的参数也可以指定默认值
:defaults
get 'photos/:id', to: 'photos#show', defaults: {format: 'jpg'}
Rails会把 /photos/12 路径映射到 Photos#show 动作上,并把 params[:format] 设为 'jpg'
当然 defaults 还有块的形式,可以为多个路由定义默认值:
defaults format: :json do resources :photos end
当然需要注意的是查询参数是不会覆盖默认值的
可以使用 :as 选项来为路由命名
:as
get 'exit', to: 'sessions#destroy', as: :logout
这个路由声明会创建 logout_path 和 logout_url 这两个具名辅助方法
路由命名可以覆盖资源路由定义的路由辅助方法:
get ':username', to: 'users#show', as: :user
通过使用 match 方法和 :via 选项,可以一次匹配多个HTTP方法:
match 'photos', to: 'photos#show', via: [:get, :post]
通过 via: :all 选项,路由可以匹配所有的HTTP方法
match 'photos', to: 'photos#show', via: :all
把GET和POST请求映射到同一个控制器动作上会带来安全隐患,通常我们应该避免将不同的HTTP方法映射到同一个控制器动作上。
使用 :contraints 选项可以约束动态片段的格式:
:contraints
get 'photos/:id', to: 'photos#show', contraints: { id: /[A-Z]\d{5}/ }
这个路由会匹配 /photos/A12345 路径,但不会匹配 /photos/893 路径,这个还可以简写为:
get 'photos/:id', to: 'photos#show', id: /[A-Z]\d{5}/
:contraints 选项的值可以是正则表达式,但不能使用 ^ 符号,比如下面就是错误的:
get '/:id', to: 'articles#show', constraints: { id: /^\d/ }
路由通配符用于指定特殊参数,这个参数会匹配路由的所有剩余部分:
get 'photos/*other', to: 'photos#unknown'
这个路由会匹配 photos/12 和 /photos/long/path/to/12 路径,并把 params[:other] 分别设置为 "12" 和 "long/path/to/12"。像 *other 这样以星号开头的片段,称作“通配符片段”。
通配符片段可以出现在路由中的任何位置:
get 'books/*section/:title', to: 'books#show'
在路由中可以使用 redirect 辅助方法进行重定向
redirect
get '/stories', to: redirect('/articles')
重定向中也可以使用源路径的动态片段:
get '/stories/:name', to: redirect('/articles/%{name}')
redirect 默认是301永久重定向,有些浏览器和代理服务器缓存这种类型的重定向,从而导致无法访问重定向前的网页,为了避免这种情况,我们可以使用 :status 选项修改响应状态:
:status
get '/stories/:name', to: redirect('/stories/%{name}'), status: 302
root 方法指明如何处理根路径的请求:
root to: 'pages#main'
简易写法
root 'pages#main'
root路由只处理 GET 请求
声明路由时,可以直接使用 Unicode 字符:
get "忽如寄" , to: 'welcome#index'
:controller 选项用于显式指定资源使用的控制器:
:controller
resources :photos, controller: 'images'
这时路由会把 /photos 路径映射到 Images 控制器上
对于命名空间中的控制器,可以使用目录表示法:
resources :user_permissions, controller: 'admin/user_permissions'
:constraints 选项用于指定隐式 ID 必须满足格式要求
:constraints
resources :photos, constraints: {id: /[A-Z][A-Z][0-9]+/ }
这时会约束 :id 参数,路由不会匹配 /photos/1 路径,会匹配 /photos/PR12
当然也可以同时约束多个路由:
constraints(id: /[A-Z][A-Z][0-9]+/) do resources :photos resources :accounts end
resources :photos, as: 'images'
此时的具名辅助方法被修改为:
:path_names 选项用于覆盖路径中自动生成的 new 和 edit 片段
:path_names
resources :photos, path_names: { new: 'make', edit: 'change' }
这个路由能够识别以下路径:
/photos/make /photos/1/change
:path_names 选项不会改变控制器动作的名称,仍然映射到 new 和 edit 动作上
Rails 默认会为每个 REST 式路由创建7个默认动作,可以使用 :only 和 :except 选项来微调此行为。 :only 选项用于指定想生成的路由:
:only
:except
resources :photos, only: [:index, :show]
:except 选项用于指定不想生成的路由:
resources :photos, except: :destroy
使用 scope 方法,可以修改 resources 方法生成的路径名称:
scope
scope(path_names: {new: 'neu', edit: 'bearbeiten'}) do resources :categories, path: 'kategorien' end
这会覆盖自动生成的辅助方法名称:
resources :magazine do resources :ads, as: 'periodical_ads' end
这会生成 magazine_periodical_ads_url 等辅助方法。
magazine_periodical_ads_url
The text was updated successfully, but these errors were encountered:
No branches or pull requests
资源路由
一行代码完成资源资源路由声明:
这会创建7个不同的路由,这些路由会映射到
Photos
控制器上。这样4个URL地址就会映射到7个不同的控制器动作上。
用于生成路径和URL地址的辅助方法
在创建资源路由时,会同时创建多个可以在控制器中使用的辅助方法,如上面的资源路由会创建以下方法:
photos_path
:返回值为 /photosnew_photos_path
:返回值为 /photos/newedit_photo_path(:id)
:返回值为 /photos/:id/editphoto_path(:id)
:返回值为 /photos/:id这些方法都有对应的_url形式(photos_url),前者返回的是路径,后者返回的是完整的url地址。
同时定义多个资源
可以同时定义多个资源路由:
等价于:
单数资源
使用
![](https://camo.githubusercontent.com/03a55526fd0042ca6fc2315b93ba9e8b507324b5b1f5f17c623c302d46a1bbc4/68747470733a2f2f75706c6f61642d696d616765732e6a69616e7368752e696f2f75706c6f61645f696d616765732f313634313338302d333939333465396465376639623264302e706e673f696d6167654d6f6772322f6175746f2d6f7269656e742f7374726970253743696d61676556696577322f322f772f31323430)
resource
方法可以创建单数资源,这会创建6个不同的路由:有时候在复数资源中希望能够不使用ID就能查找资源,如显示当前登录用户的信息:
如果
get
方法的to选项的值是字符串,那么这个字符串应该使用controller#action形式,如果是表示动作的符号,则还需要添加controller选项:控制命名空间和路由
把控制器放入同一命名空间是非常常见的,如将管理员有关的控制器置于
Admin::
命名空间中,这样可以把控制器文件放在app/controllers/admin
文件夹中,在路由中这样声明:对于articles资源
![](https://camo.githubusercontent.com/1f3bbaf25334c63e433f84877e837591aa36ec1a3fcb18cdde4afb83bd83a1c7/68747470733a2f2f75706c6f61642d696d616765732e6a69616e7368752e696f2f75706c6f61645f696d616765732f313634313338302d333338353165633934373736663665612e706e673f696d6167654d6f6772322f6175746f2d6f7269656e742f7374726970253743696d61676556696577322f322f772f31323430)
如果想把 /articles 路径(不带/admin前缀)映射到Admin::Articles控制器上,可以这样声明:
或者
或者:
嵌套资源
有些资源是其他资源的子资源,这种情况非常常见:
通过嵌套路由来反映模型关联:
对于嵌套路由,可以不断嵌套:
但是显然嵌套太深是非常麻烦的,经验告诉我们嵌套资源层级不应该超过一层,而避免嵌套过深的方法之一就是把动作集合放在父资源中,这样既可以表明层级关系,又不必嵌套成员动作:
当然,使用
:shallow
选项可以简化上面的代码:当然,在复选项中使用
:shallow
选项,这样会在所有的子资源中使用:shallow
选项:也可以使用
shallow
方法创建作用域,使得所有嵌套均为浅层嵌套:使用scope方法也可以来定义浅层路由,且有两个选项,
:shallow_path
选项会为成员路径添加前缀::shallow_prefix
选项会为具名方法添加指定前缀:路由concern
路由concern用于声明公共路由,公共路由可以在其他资源和路由中重复使用:
使用:
相当于:
从对象创建路径和RUL地址
除了使用路由辅助方法,Rails还可以从参数数组创建路径和URL地址,假如有以下路由:
使用
magazine_ad_path
方法时,可以传入Magazine和Ad的实例,而不只是数字ID:还可以使用
url_for
方法时传入一组对象,Rails会自动确定对应的路由:Rails能够识别各个实例,自动使用
magazine_ad_path
辅助方法。当然在使用link_to
等辅助方法时,可以只指定对象,而不必完整调用url_for
方法:如果想要链接到其他控制器动作,只需把动作名称作为第一个元素插入对象数组即可:
这样就可把模型实例看做URL地址,这是使用资源式风格最关键的优势之一。
非资源式路由
和资源路由自动生成一系列路由不同,这时需要分别声明各个路由,非资源路由可以把任意URL地址映射到控制器动作的路由。
绑定参数
声明普通路由时,可以使用符号作为参数:
在处理 /photos/1 请求时,会把请求映射到 Photos 控制器的 display 动作上,并把参数1传入params[:id],并将路由映射到 PhotosController#display 上,并且 /photos 请求也会映射到这个控制器动作上,因为 :id 在括号中,是可选参数。
动态片段
声明普通路由时,允许使用多个动态片段,动态片段会传入params,以便在控制器动作中使用:
/photos/1/2 请求会被映射到 photos#show 动作上,这时 params[:id] 的值是 1 ,params[:user_id] 的值是 2
查询字符串
params 也包含了查询字符串中的所有参数,如:
/photos/1?user_id=2 请求也会映射到 Photos#show 控制器动作上,这时params的值是
定义默认值
:defaults
选项设定的散列为路由定义默认值,未通过动态片段定义的参数也可以指定默认值Rails会把 /photos/12 路径映射到 Photos#show 动作上,并把 params[:format] 设为 'jpg'
当然 defaults 还有块的形式,可以为多个路由定义默认值:
当然需要注意的是查询参数是不会覆盖默认值的
为路由命名
可以使用
:as
选项来为路由命名这个路由声明会创建 logout_path 和 logout_url 这两个具名辅助方法
路由命名可以覆盖资源路由定义的路由辅助方法:
HTTP方法约束
通过使用 match 方法和 :via 选项,可以一次匹配多个HTTP方法:
通过 via: :all 选项,路由可以匹配所有的HTTP方法
把GET和POST请求映射到同一个控制器动作上会带来安全隐患,通常我们应该避免将不同的HTTP方法映射到同一个控制器动作上。
片段约束
使用
:contraints
选项可以约束动态片段的格式:这个路由会匹配 /photos/A12345 路径,但不会匹配 /photos/893 路径,这个还可以简写为:
:contraints 选项的值可以是正则表达式,但不能使用 ^ 符号,比如下面就是错误的:
路由通配符和通配符片段
路由通配符用于指定特殊参数,这个参数会匹配路由的所有剩余部分:
这个路由会匹配 photos/12 和 /photos/long/path/to/12 路径,并把 params[:other] 分别设置为 "12" 和 "long/path/to/12"。像 *other 这样以星号开头的片段,称作“通配符片段”。
通配符片段可以出现在路由中的任何位置:
重定向
在路由中可以使用
redirect
辅助方法进行重定向重定向中也可以使用源路径的动态片段:
redirect 默认是301永久重定向,有些浏览器和代理服务器缓存这种类型的重定向,从而导致无法访问重定向前的网页,为了避免这种情况,我们可以使用
:status
选项修改响应状态:使用 root 方法
root 方法指明如何处理根路径的请求:
简易写法
root路由只处理 GET 请求
unicode 字符路由
声明路由时,可以直接使用 Unicode 字符:
自定义资源路由
指定控制器
:controller
选项用于显式指定资源使用的控制器:这时路由会把 /photos 路径映射到 Images 控制器上
对于命名空间中的控制器,可以使用目录表示法:
指定约束
:constraints
选项用于指定隐式 ID 必须满足格式要求这时会约束 :id 参数,路由不会匹配 /photos/1 路径,会匹配 /photos/PR12
当然也可以同时约束多个路由:
覆盖具名路由辅助方法
此时的具名辅助方法被修改为:
![](https://camo.githubusercontent.com/8d12083ba7b729ac6ae565d24462842af2da8af6d64d8a69f62626e3173ebd69/68747470733a2f2f75706c6f61642d696d616765732e6a69616e7368752e696f2f75706c6f61645f696d616765732f313634313338302d383832633262333937663463313133342e706e673f696d6167654d6f6772322f6175746f2d6f7269656e742f7374726970253743696d61676556696577322f322f772f31323430)
覆盖 new 和 edit 片段
:path_names
选项用于覆盖路径中自动生成的 new 和 edit 片段这个路由能够识别以下路径:
:path_names 选项不会改变控制器动作的名称,仍然映射到 new 和 edit 动作上
限制创建的路由
Rails 默认会为每个 REST 式路由创建7个默认动作,可以使用
:only
和:except
选项来微调此行为。:only
选项用于指定想生成的路由::except
选项用于指定不想生成的路由:本地化路径
使用
scope
方法,可以修改 resources 方法生成的路径名称:嵌套资源使用 :as 选项
这会覆盖自动生成的辅助方法名称:
这会生成
magazine_periodical_ads_url
等辅助方法。The text was updated successfully, but these errors were encountered: