Rails URL路由
rails URL路由的最权威文档当然是其官方站点Rails routing from the outside in,我这里只提几个文档中常用的要点。
1.CRUB
由resources建立的资源,是rails中最常见的路由方式,不用多说。
resources :photos
2.单例资源
单例资源也比较常用,官方文档上举的例子很形象也很常见,用户user需要拥有一个profile资源,而每个用户必然只有一个profile,所以如果生成类似/profiles/:id的URL显然是不美观的,此时就需要单例资源,单例资源的生成使用的是单数形式方法resource:
resource :profile
该语句生成的路由如下:
profile POST /profile(.:format) profiles#create
new_profile GET /profile/new(.:format) profiles#new
edit_profile GET /profile/edit(.:format) profiles#edit
GET /profile(.:format) profiles#show
PATCH /profile(.:format) profiles#update
PUT /profile(.:format) profiles#update
DELETE /profile(.:format) profiles#destroy
3.嵌入的路由
适用于某种资源必须依赖于另一种资源才有意义,比如某些comment必然在针对的event下存在,所以comment就必须依赖于event。
resources :events do
resources :comments
end <div class='bogus-wrapper'><notextile><figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span> <span class='line-number'>2</span> <span class='line-number'>3</span> <span class='line-number'>4</span> <span class='line-number'>5</span> <span class='line-number'>6</span> <span class='line-number'>7</span> <span class='line-number'>8</span> <span class='line-number'>9</span> <span class='line-number'>10</span> <span class='line-number'>11</span> <span class='line-number'>12</span> <span class='line-number'>13</span> <span class='line-number'>14</span> <span class='line-number'>15</span>
</pre></td><td class=’code’><pre>events_comments GET /events/comments(.:format) comments#index
POST /events/comments(.:format) comments#create
new_events_comment GET /events/comments/new(.:format) comments#new
edit_events_comment GET /events/comments/:id/edit(.:format) comments#edit
events_comment GET /events/comments/:id(.:format) comments#show
PATCH /events/comments/:id(.:format) comments#update
PUT /events/comments/:id(.:format) comments#update
DELETE /events/comments/:id(.:format) comments#destroy
events POST /events(.:format) events#create
new_events GET /events/new(.:format) events#new
edit_events GET /events/edit(.:format) events#edit
GET /events(.:format) events#show
PATCH /events(.:format) events#update
PUT /events(.:format) events#update
DELETE /events(.:format) events#destroy
</pre></td></tr></table></div></figure></notextile></div>
对应的也自动生成了诸如event_comment_path之类的url 帮助方法。对于嵌入式资源,官方建议不要超过两层。最简单的理由,路由层次过深,除了增加逻辑的复杂度外,也得不到任何好处。
4.namespace和scope路由
以下规则同时适用于resources和controller。
比如,如果想要在特定的命名空间(admin)下访问某个资源(post),这时就可以利用namespace。
namespace :admin do
resources :posts
end
此时,处理该路由的controller是Admin::PostsController,体现在rails工程中是在controller文件夹下的admin文件夹下的posts_controller.rb文件。而产生的路由全部以/admin开头:
1 2 3 4 5 6 7 8 |
|
一言以蔽之,由namespace产生的资源路由,controller和url都由该namespace作“前缀”。
如果需要让资源路由没有前缀,而又希望该路由url被某个模块下的controller受理,那么就需要使用 scope。
scope module: 'admin' do
resources :posts
end
1 2 3 4 5 6 7 8 |
|
由rake routes输出可以看出,路由url没有了admin前缀,而posts资源都由admin模块下的Admin::PostsController受理。
一言以蔽之,带module的scope产生的资源路由,路由url无“前缀”,controller以module指定模块为“前缀”。
反过来,如果希望给资源附加一个前缀,而由普通controller受理该url,则需要另一种形式的scope:
scope '/admin' do
resources :posts
end
1 2 3 4 5 6 7 8 |
|
此时,资源posts每个url都附加了/admin为前缀,而受理这些url的是PostsController。
一言以蔽之,这种形式的scope产生的资源路由,路由url有“前缀”,controller无“前缀”。
另外,这种形式的路由还有一种简写:
resources :posts, path: '/admin/posts'
该简写和使用scope产生的结果完全一样。不过,path还有另外的用途,如果保持controller及url helper不变,仅仅希望为url路由中的资源改个名称,这时path就派上用场了:
resources :posts, path: '/articles'
1 2 3 4 5 6 7 8 |
|
5.新增RESTful动词
以下规则同样适用于resources和controller。
resources :photos do
get 'preview', on: :member
end
该语句为某个特定photo新增了一个preview动作,该动作是一个get请求,默认photos_controller中存在一个preview方法处理该动作。
类似的,如果需要为photos集合新增一个动词,只需要将语句中member改成collection即可。
如果,需要为特定photo增加多个动词preview1和preview2,改成下面的形式即可,甚至可以指定 controller中处理该请求的方法,以及自定义url helper:
resources :photos do
member do
get 'preview1'=>:pre1, as:"p1"
get 'preview2'=>:pre2, as:"p2"
end
end
1 2 |
|
6.非resourceful路由
使用参数:
controller :photos do
get 'check/:id',:to=>:check
end
产生的路由输出如下:
GET /check/:id(.:format) photos#check
在执行该get请求如/check/23,后photos_controller的check方法受理该请求,并在params中将参数设置为23。
限制参数格式:
get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ }
该路由规则能接受/photos/A12345却不能接受/photos/893。
指定请求的默认类型:
get 'articles/:id', to: 'articles#show', defaults: { format: 'xml' } 若get请求/articles/2,该路由规则会自动将params的params[:format]置为"xml"。
该方法仅仅是在请求未指定format时指定默认类型,如果需要某个controller仅接受某些格式的请求如xml和json,则可以在该controller类定义中添加如下代码,这在书写api时常常用到:
respond_to :json, :xml
更换资源的controller:
如果不希望为某个资源使用默认的controller,则:
resources :photos, controller: 'images'
此时photos资源的所有请求都由images_controller受理,而photos的路由url和url helper都不变。
限制资源的默认动作:
如果仅希望使用资源的部分动作,如仅使用资源photos的index和show动作:
resources :photos, only: [:index, :show]
或者使用除了destroy动作外的所有默认动作:
resources :photos, except: :destroy 还可以使用:all(所有默认动作),:none(没有默认动作):
resources :photos, :only=>:none
为new和edit的url路由改名:
resources :photos, path_names: { new: 'make', edit: 'change' }
产生的新路由为:
/photos/make
/photos/1/change
而此时受理该路由的方法仍为new和edit,即controller中的方法并未改名。