一行代码完成资源资源路由声明:html
resources :photos
复制代码
这会建立7个不一样的路由,这些路由会映射到 Photos
控制器上。正则表达式
这样4个URL地址就会映射到7个不一样的控制器动做上。json
在建立资源路由时,会同时建立多个能够在控制器中使用的辅助方法,如上面的资源路由会建立如下方法:数组
photos_path
:返回值为 /photos浏览器
new_photos_path
:返回值为 /photos/new缓存
edit_photo_path(:id)
:返回值为 /photos/:id/edit安全
photo_path(:id)
:返回值为 /photos/:idruby
这些方法都有对应的_url形式(photos_url),前者返回的是路径,后者返回的是完整的url地址。bash
能够同时定义多个资源路由:服务器
resources :photos, :books, :videos
复制代码
等价于:
resources :photos
resources :books
resources :videos
复制代码
使用 resource
方法能够建立单数资源,这会建立6个不一样的路由:
有时候在复数资源中但愿可以不使用ID就能查找资源,如显示当前登陆用户的信息:
get 'profile', to: 'users#show'
复制代码
若是 get
方法的to选项的值是字符串,那么这个字符串应该使用controller#action形式,若是是表示动做的符号,则还须要添加controller选项:
get 'profile', to: :show, controller: 'users'
复制代码
把控制器放入同一命名空间是很是常见的,如将管理员有关的控制器置于 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
选项能够简化上面的代码:
resources :articles do
resources :comments, shallow: true
end
复制代码
固然,在复选项中使用 :shallow
选项,这样会在全部的子资源中使用 :shallow
选项:
resources :articles, shallow: true do
resources :comments
resources :quotes
end
复制代码
也可使用 shallow
方法建立做用域,使得全部嵌套均为浅层嵌套:
shallow do
resources :articles do
resources :comments
resources :quotes
resources :drafts
end
end
复制代码
使用scope方法也能够来定义浅层路由,且有两个选项,:shallow_path
选项会为成员路径添加前缀:
scope shallow_path: "sekret" do
resources :articles do
resources :comments, shallow: true
end
end
复制代码
: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地址,假若有如下路由:
resources :magazine do
resources :ads
end
复制代码
使用 magazine_ad_path
方法时,能够传入Magazine和Ad的实例,而不仅是数字ID:
<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %>
复制代码
还可使用 url_for
方法时传入一组对象,Rails会自动肯定对应的路由:
<%= link_to 'Ad details', url_for([@magazine, @ad]) %>
复制代码
Rails可以识别各个实例,自动使用 magazine_ad_path
辅助方法。固然在使用 link_to
等辅助方法时,能够只指定对象,而没必要完整调用 url_for
方法:
<%= 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
选项设定的散列为路由定义默认值,未经过动态片断定义的参数也能够指定默认值
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
选项来为路由命名
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
选项能够约束动态片断的格式:
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
辅助方法进行重定向
get '/stories', to: redirect('/articles')
复制代码
重定向中也可使用源路径的动态片断:
get '/stories/:name', to: redirect('/articles/%{name}')
复制代码
redirect 默认是301永久重定向,有些浏览器和代理服务器缓存这种类型的重定向,从而致使没法访问重定向前的网页,为了不这种状况,咱们可使用 :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
选项用于显式指定资源使用的控制器:
resources :photos, controller: 'images'
复制代码
这时路由会把 /photos 路径映射到 Images 控制器上
对于命名空间中的控制器,可使用目录表示法:
resources :user_permissions, controller: 'admin/user_permissions'
复制代码
:constraints
选项用于指定隐式 ID 必须知足格式要求
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 片断
resources :photos, path_names: { new: 'make', edit: 'change' }
复制代码
这个路由可以识别如下路径:
/photos/make
/photos/1/change
复制代码
:path_names 选项不会改变控制器动做的名称,仍然映射到 new 和 edit 动做上
Rails 默认会为每一个 REST 式路由建立7个默认动做,可使用 :only
和 :except
选项来微调此行为。 :only
选项用于指定想生成的路由:
resources :photos, only: [:index, :show]
复制代码
:except
选项用于指定不想生成的路由:
resources :photos, except: :destroy
复制代码
使用 scope
方法,能够修改 resources 方法生成的路径名称:
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
等辅助方法。