欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Rails路由 转摘 Rails正则表达式REST浏览器ActiveRecord

程序员文章站 2024-03-19 20:01:28
...
此文原文在http://guides.rubyonrails.org/routing.html。这是我根据自己的理解作的一些笔记。

1 使用路由有两上目的
1.1 连接URLs
当Rails应用收到HTTP的请求时,Rails会响应
GET /patients/17

Rails中的路由引擎是一个代码片断。在这个例子中,可能会运行patients控制器的show方法。显示ID为17的详细信息。

1.2 从代码生成URLs
路由也是可以反向工作的。假如应用中包含下面的代码:
@patient = Patient.find(17)

<%= link_to "Patient Record", patient_path(@patient) %>

这个路由引擎片断会转化成类似http://example.com/patients/17这样的URL。使用这样的方法可以减少代码中的硬编码,而且这样更容易阅读。

2 快览routes.rb
在Rails中路由有两个部分,一个是Rails提供的路由引擎本身,和文件config/routes.rb,文件包含了将被应用程序应用的实际路由。

2.1 处理文件
routes.rb文件主要关心的内容是ActionController:Routing::Routes.draw方法后的一个代码块。在应用程序中一般每一行开始一个路由,在这个文件中我们将会发现有5个主要的类型:
·RESTful Routes # 资源路由
·Named Routes    # 命名路由
·Nested Routes   # 嵌套路由
·Regular Routes # 正则路由
·Default Routes # 默认路由

当有请求时,routes.rb文件会从上至下进行匹配处理,如果没有匹配的,就返回404错误给浏览器。

2.2 RESTful Routes
RESTful路由的优势在于通过一个简单的声明,就能得到包含很多REST方式的路由信息。一个RESTful路由看起像这样:
map.resources :books

2.3 Named Routes
命名路由在给一个定义的路由取一个名字,这样让代码就更容易阅读。
map.login '/login', :controller => 'sessions', :action ='new'

2.4 Nested Routes
嵌套路由让我们声明一个资源包含另一个资源。比如,应用程序中包含一个parts,而每个parts又属于一个assembly,就可以这样声明嵌套路由。

map.resources :assemblies do |assemblies|
assemblies.resources :parts
end

2.5 Regular Routes
在更多的应用中,可能看到一些非RESTful的路由设置,它通过特定的action来联接。比如:
map.connect 'parts/:number', :controller => 'inventory', :action => 'show'

2.6 Default Routes
routes.rb会包含下面的代码:
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
这些默认的路由声明是在创建Rails应用时自动创建的。如果在你的应用程序中使用RESTful路由,那建议把他们移除。

3 Rails默认的RESTful路由
RESTful路由是当前Rails中的标准路由。你会喜欢上这个新应用的。在使用它之前,有必要花点时间来了解它是如何工作的,但这些时间是花得值得的。而且,使用这种风格的路由,让代码更容易阅读。

3.1 什么是REST?
REST的是Roy Fielding's 博士在2000年他的论文中出来的一种软件架构风格,REST全名Representational State Transfer,中文译为表象化状态迁移。它归结了两点主要原则:
·使用资源标识符来描述资源。
·系统组件之间的资源状态迁移。

例如:Rails的一个请求像这样:
DELETE /photos/17

这会归结为一个ID为17的photo资源,并要求使用的删除操作来处理这个资源。在WEB应用程序的架构中,REST是一种很自然的风格。Rails遵守一种约定,让处理复杂的RESTful更自然。


3.2 CRUD, Verbs and Actions
在Rails里,一个RESTful提供了一个HTTP vers, 控制器action和数据库CRUD操作之间的映射。一个简单的资源路由:

map.resources :photos

在你的应用程序中,这一行会创建7个不的路由。
HTTP verb    URL    controller     action     used for
GET        /photos        Photos     index         display a list of all photos
GET        /photos/new        Photos     new         return an HTML form for creating a new photo
POST       /photos        Photos     create         create a new photo
GET        /photos/1        Photos     show         display a specific photo
GET        /photos/1/edit Photos     edit           return an HTML form for editing a photo
PUT        /photos/1        Photos     update         update a specific photo
DELETE     /photos/1        Photos     destroy     delete a specific photo

3.3 URLs和Paths
在应用程序内部,创建了一个RESTful路由就会生成一些有用的辅助方法:
·photos_url和photos_path映射了index和create方法的路径
·new_photo_url和new_photo_path映射了new方法的路径
·edit_photo_url和edit_photo_path映射了edit方法的路径
·photo_url和photo_path映射了show, update和destroy方法的路径
在这个例子中_url辅助方法会生成完整的URL的绝对路径,_path会生成相对路径。
例如:
photos_url # => "http://www.example.com/photos"
photos_path #=> "/photos"

3.4 在同一个时间定义多资源。
如果要创建多资源,可以调用map.resources方法:
map.resources :photos, :books, :videos
这一行也可以分开来写:
map.resources :photos
map.resources :books
map.resources :videos

3.5 单资源
在应用程序中也可以定义单资源路由。就要需要使用map.resource方法,而不是map.resources方法。例如:
map.resource :geocoder
这将生成6个不同的路由:

Http verb      URL          controller action           used for
GET         /geocoder/new   Geocoders     new     return an HTML form for creating the new geocoder
POST         /geocoder         Geocoders     create     create the new geocoder
GET         /geocoder         Geocoders     show     display the one and only geocoder resource
GET         /geocoder/edit Geocoders     edit     return an HTML form for editing the geocoder
PUT         /geocoder         Geocoders     update     update the one and only geocoder resource
DELETE         /geocoder         Geocoders     destroy   delete the geocoder resource

虽然资源是定义的单数,但匹配的控制器还是复数。

一个单资源路生成的辅助方法
·new_geocoder_url和new_geocoder_path映射了new方法路径
·edit_geocoder_url和edit_geocoder_path映射了edit方法路径
·geocoder_url和geocoder_path映射了show,create,update和destroy方法路径


3.6 定置资源
虽然约定的RESTful路由就能满足大多数的应用了,还是有几个自定义的方法让RESTful路由工作。这些选项包括:
·:controller
·:singular
·:requirements
·:conditions
·:as
·:path_names
·:path_prefix
·:name_prefix
·:only
·:except
还可以通过:member和:collection添加额外的资源。

3.6.1 使用:controller
:controller选项让我们在资源中使用一个不同的控制名称。比如:
map.resources :photos, :controller => "images"

URLs还是包含photo,但是路径请求就是images控制器了。
HTTP verb    URL    controller     action     used for
GET        /photos        Images     index         display a list of all images
GET        /photos/new        Images     new         return an HTML form for creating a new image
POST       /photos        Images     create         create a new image
GET        /photos/1        Images     show         display a specific image
GET        /photos/1/edit Images     edit           return an HTML form for editing a image
PUT        /photos/1        Images     update         update a specific image
DELETE     /photos/1        Images     destroy     delete a specific image
辅助方法会以资源的名称来生成,不是控制器的名称,所以在这个例子中,仍然得到的是photos_path, new_photo_path等方法。

3.7 控制器命名空间和路由
Rails允许你把保存在app/controllers路径下的文件夹通过命名空间把控制器分组。:controller选项就提供了一个方便的方法。比如,你有一个资源控制器是为admin用户准备的,保存在admin文件夹下。
map.resources :adminphotos, :controller => "admin/photos"
如果你使用控制器命令空间,必须Rails路由代码中一个微秒的地方:路由总是试图从上次的合理的请求保存更多的命名空间。例如,在视图中使用是adminphoto_path方法,生成一个链接<%=link_to "show", adminphoto(1) %>最终会生成这样的路径:admin/photos/show。但如,如果你有<%= link_to "show", {:controller => "photos", :action => "show"} %>代码,仍然会生成adminphoto_path,这是因为Rails将生成的show视图的URL关链到当前的URL.
如果要保证使用的是顶层的控制咕嘟,就要在控制器名称的前面加上斜线/。比如这样:
<%= link_to "show", {:controller => "/photos", :action => "show" } %>

可以通过:namespace选项提定命名空间:
map.resources :adminphotos, :namespace => "admin", :controller => "photos"

当联合使用with_options是相当有用的,这会把多个命名空间组织起来。
map.with_options(:namespace => "admin") do |admin|
admin.resources :photos, :videos
end

这和下的代码是相同的。
map.resources :photos, :namespace => "admin"
map.resources :videos, :namespace => "admin"

with_options就是可以把相同的部分取出来,减少重复,后面还会专门介绍。

3.7.1 :singular
如果没有足够的理由不要把复数的资源转换为单数,可以用:singular选项来重写复数的资源。
map.resources :teeth, :singular => "tooth"

3.7.2 :requirements
在RESTful路由中能够使用:requirements选项,强加一种格式给:id参数。例如:
map. resources :photos, :requiremets => {:id => /[A-Z][A-Z][0-9]+/}
这个声名就强制:id参数匹配一个正则表达式。所以在这个例子中,/photos/1将不能被识别,但是/photos/RR27就可以。

3.7.3 :conditions
在Rails路由里条件一般是用来设置HTTP verb的个别路由,理论上你可以这样设置它,但是在实践中这并不是一个好主意。(后面会有更多关于条件的讨论)

3.7.4 :as
:as选项会用新的名称重写标准的路径。例如:
map.resources :photos, :as => "images"
现在URLs就包含image了,但路由请求还是Photos控制器。
HTTP verb    URL    controller     action     used for
GET        /images        Photos     index         display a list of all photos
GET        /images/new        Photos     new         return an HTML form for creating a new photo
POST       /images        Photos     create         create a new photo
GET        /images/1        Photos     show         display a specific photo
GET        /images/1/edit Photos     edit           return an HTML form for editing a photo
PUT        /images/1        Photos     update         update a specific photo
DELETE     /images/1        Photos     destroy     delete a specific photo
辅助方法会以资源的名称来生成,不是路径的名称,所以在这个例子中,仍然得到的是photos_path, new_photo_path等方法。
这里要注意一下和:controller选项的区别。

3.7.5 :path_names
:path_names选项可以重写在URLs中自动生成的"new"和"edit"部分:
map.resources :photos, :path_names => {:new => 'make', :edit => 'change'}
URLs就变成下面这样了:
/photos/make
/photos/1/change
实际的方法名称没有改变,只是URLs变化了。

3.7.6 :path_prefix
:path_prefix选项在路径前面增加一个附件前缀。例如:在应用程序中图片属于某个摄影师,就可以这样声明路由:
map.resources :photos, :path_prefix => "/photographers/:photographer_id'
路径就是这样的:
/photographers/1/photos/2
/photographers/1/photos

3.7.7 :name_prefix
使用:name_prefix可以避免路由间的冲突。当你有两个相同名称的资源就可以使用:path_prefix映射为不同。例如:
map.resources :photos, :path_prefix => '/photographers/:photographer_id', :name_prefix => 'photographer_'
map.resources :photos, :path_prefix => '/agencies/:agency_id', :name_prefix => 'agency_'
这个联合就会得到像photographer_photos_path和agency_edit_photo_path这样的辅助方法。

3.7.8Rails路由 转摘
            
    
    
        Rails正则表达式REST浏览器ActiveRecordnly和:except
默认情况下,Rails会根据默认的方法(index, show, new, create, edit, update和destroy)创建7个路径。可以使用:only和:except选项来调整这个行为。:only指定仅仅是要生成的路由。
map.resources :photos,Rails路由 转摘
            
    
    
        Rails正则表达式REST浏览器ActiveRecordnly => [:index, :show]
这个声明就,GET请注/photos就会成功,POST请求就会失败。

:except选项是指定哪个路由不被产生。
map.resources :photos, :except => :destroy

3.8 嵌套资源
一些资源通过有一些子资源。假如,应用程序中包含这些模型:
class Magazine < ActiveRecord::Base
has_many :ads
end

class Ad < ActiveRecord::Base
belongs_to :magazine
end
每一个ad属于一个magazine,嵌套路由来抓取这种关系,声明如下:
map.resources :magazines do |magazine|
magazine.resources :ads
end
快捷写法:
map.resources :magazines, :has_many => :ads
这个声明为ads创建路由:

HTTP verb     URL            controller action     used for
GET     /magazines/1/ads        Ads        index     display a list of all ads for a specific magazine
GET     /magazines/1/ads/new        Ads        new             return an HTML form for creating a new ad belonging to a specific magazine
POST     /magazines/1/ads        Ads        create     create a new ad belonging to a specific magazine
GET     /magazines/1/ads/1        Ads        show     display a specific ad belonging to a specific magazine
GET     /magazines/1/ads/1/edit Ads        edit     return an HTML form for editing an ad belonging to a specific magazine
PUT     /magazines/1/ads/1        Ads        update     update a specific ad belonging to a specific magazine
DELETE     /magazines/1/ads/1        Ads        destroy     delete a specific ad belonging to a specific magazine

创建了一些类似于magazine_ads_url和edit_magazine_ad_path的辅助方法。

3.8.1 :name_prefix
:name_prefix选项重写在嵌套路由辅助方自动生成的前缀。例如:
map.resources :magazines do |magazine|
magazine.resources :ads, :name_prefix => 'periodical'
end
将创建类似于periodical_ads_url和periodical_edit_ad_path的辅助方法。也可以使用:name_prefix去禁止前缀:
map.resources :magazines do |magazine|
magazine.resources :ads, :name_prefix => nil
end
将创建类似于ads_url和edit_ad_path的辅助方法。在调用这些方法时要注意提供id参数:
ads_url(@magazine)
edit_ad_path(@magazine, @ad)

3.8.2 :has_one和:has_many
:has_one和:has_many为简单的嵌套路由提供了简洁的标记。使用:has_one嵌套单资源,:has_many嵌套多资源:
map.resources :photos, :has_one => :photographer, :has_many =>[:publications, :versions]
这和下现的声名是一样的:
map.resources :photos do |photo|
photo.resource :photographer
photo.resources :publications
photo.resources :versions
end

3.8.3 限制嵌套
如果你愿意,嵌套资源里还可以再嵌套资源,比如:
map.resources :publishers do |publisher|
publisher.resources :magazines do |magazine|
    magazine.resources :photos
end
end
然而,没有使用name_prefix => nil,深度嵌套资源会带来麻烦,在这个例子中,会有像下面这样的URLs产生:
/publishers/1/magazines/2/photos/3
对应的辅助方法是publisher_magazine_photo_url,需要指定三层对象,确实不是一个好的设计,好的思想是让资源嵌套不要超过一层。

3.8.4 浅层嵌套
:shallow选项的使用有效的解决了深层嵌套的困难。可以在任何层级指定这个选项,然后嵌套资源路径会参考特定成员(也就是有:id的参数)将不再使用父路径前缀和名称前缀。看看这意味着什么,考虑一下下面的路由设置:
map.resources :publishers, :shallow => true do |publisher|
publisher.resources :magazines do |magazine|
    magazine.resources :photos
end
end
这个就会识别像下面这样的路由:
/publishers/1   ==> publisher_path(1)
/publishers/1/magazines ==> publisher_magazines_path(1)
/magazines/2 ==> magazine_path(2)
/magazines/2/photos ==> magazines_photos_path(2)
/photos/3 ==> photo_path(3)

如果你愿意,也可以结合:has_one和:has_many选项使用:shallow

map.resources :publishers, :has_many => {:magazines => :photos}, :shallow => true

3.9 从数组中生成路由
Rails能从一个数组参数中生成RESTful路由。比如,有下面这样的声名:
map.resources :magazines do |magazine|
magazine.resources :ads
end

Rails将生成像magazine_ad_path这样的辅助方法,你可以这样使用它:
<%= link_to "Ad details", magazine_ed_path(@magazine, @ad) %>
用对象的数组可以同样的路由:
<%= link_to "Ad details", [@magazine, @ad] %>

3.10 命名空间资源
使用:path_prefix和:name_prefix可以做些复杂的事情。比如,能够结合这两者的使用,把管理资新移动到他们自己的文件夹:
map.resources :photos, :path_prefix => 'admin', :controller => 'admin/photos'
map.resources :tags, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_tags'
map.resources :ratings, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_ratings'
一个好消息是你可以停止使用这么复杂的层级关系了。Rails提供了命名空间资源,声名如下:
map.namespace(:admin) do |admin|
admin.resources :photos,
:has_many => {:tags, :ratings}
end
正如你看到的,使用命名空间资源更简洁。比如:你将得到admin_photos_url,对应的控制器是Admin::PhotosController,并匹配admin/photos, admin_photos_ratings_path匹配/admin/photos/_photo_id_/ratings,对应的控制器是Admin::RatingsController。尽管你没有指定路径前缀,路由代码也会加上去。

3.11 添加更多的RESTful行为
你并没有受到RESTful默认的七个路由的限制,能够添加member路由(应用资源的单个实例),添加new路由(应用于创建一个新资源),或者添加collection routes(应用于资源的集合)。

3.11.1 添加Member路由
使用:member选项添加member路由:
map.resources :photos, :member => {:preview => :get}
Rails会生成路径/photos/1/preview,使用GET请求。也会创建一个preview_photo的路由辅助方法。
在member路由哈希中,每个路由可以提定一个HTTP请求方式,可以使用 :get, :put, :post, :delete, 或者:any,如果你需要多个请求方式就把它们放在数组中:
map.resources :photos, :member => {:prepare => [:get, :post]}

3.11.2 添加Collection路由
使用:collection选项添加collection路由:
map.resources :photos, :collection => {:search => :get}
Rails会生成路径/photos/search,使用GET请求。也会创建一个search_photos的路由辅助方法。
和member路由一样,collection路由也可以指定数组:
map.resources :photos, :collection => {:search => [:get, :post]}

3.11.3 添加New路由
使用:new选项添加new路由:
map.resources :photos, :new => {:upload => :post}
Rails会生成路径/photos/upload,使用POST请求。也会创建一个upload_photos的路由辅助方法。

如果想给标准的方法重新定义请求方式,可以提明方法的映射。例如:
map.resources :photos, :new => {:new => :any}
就将允许new方法,被请求到photos/new,和哪种HTTP请求方式没有关系。

4 正则路由
Rails支持正则路由——是把URLs映射到控制器和方法上。可以应用程序中使用RESTful路由和正则路由两种风格。建议多使用RESTful风格,因为这更容易编写和阅读。

4.1 Bound Parameters
设置正则路由的时候,:controller映射控制器的名称,:action映射方法的名称。例如默认的Rails路由:
map.connect ':controller/:action/:id'
如果请求是/photos/show/1,就会和这个路由做相当的匹配,就会是调用Photos控制器中的show方法,并把这个:id传入params[:id]。

4.2 通配符组件
如果你愿意,可以设置很多的通配符号:
map.connect ':controller/:action/:id/:user_id'
请求的URL是/photos/show/1/2,就会调用Photos控制器中的show方法,params[:id]就设为1,params[:user_id]就设为2。

4.3 静态文本
当创建一个路由时,可以指定一个静态的文本,例如:
map.connect ":controller/:action/:id/with_user/:user_id"
应答的路径就像这样/photos/show/1/with_user/2

4.4 Querystring参数
Rails路由在params哈希中自动选出querystring参数。例如:
map.connect ':controller/:action/:id'
/photos/show/1?user_id=2这个路径进来,就会分配Photos控制器的show方法来处理,params[:id]设为1,params[:user_id]设为2。

4.5 定义默认值
给:controller和:action设定默认值:
map.connect 'photos/:id', :controller => 'photos', :action='show'
就样可以匹配这样的路径:/photos/12

还可以使用:defaults选项:
map.connect 'photos/:id', :controller => 'photos', :action => 'show', :defaults => { :format => 'jpg' }
就同样匹配这样的路径:/photos/12,并且params[:format]设为jpg。

4.6 命名路由
命名路由就不使用connect方法了,可以使用其他的名称来创建一个命名路由。例如:
map.logout '/logout', :controller => 'sessions', :action => 'destroy'
这个路会做两件事,首先,/logout请求将被发送给Sessions控制器的destroy方法。Rails会生成logout_path和logout_url辅助方法。

4.7 路由需求
使用:requirements选项为路由参数指定一种格式:
map.connect 'photo/:id', :controller => 'photos', :action => 'show', :requirements => { :id => /[A-Z]\d{5}/ }
这个路由应答像/photo/A12345这样的URLs。也可以简写:
map.connect 'photo/:id', :controller => 'photos', :action => 'show', :id => /[A-Z]\d{5}/

4.8 路由条件
可以用:conditions选项来约束路由,现在来约束:method:
map.connect 'photo/:id', :controller => 'photos', :action => 'show', :conditions => {:method => :get}
在RESTful路由使用:conditions,可以具体指定:get, :post, :put, :delete, 或者 :any给:method。

4.9 路由通配符
路由通配符是一种指定一个详细的参数去匹配路由剩余部分的方法。例如:
map.connect 'photo/*other', :controller => 'photos', :action => 'unknow'
这个路由会匹配photo/12或者/photo/long/path/to/12,并且为params[:other]创建一个数组。

4.10 路由选项
使用:with_options把相似路由分成一组:
map.with_options :controller => 'photo' do |photo|
photo.list '', :action => 'index'
photo.delete ':id/delte', :action => 'delete'
photo.edit ':id/edit', :action => 'edit'
end


5 格式和respond_to
使用:format参数让路由可以根据不同的HTTP请求格式做不同的处理:
map.connect ':controller/:action/:id.:fromat'
匹配/photo/edit/1.xml或者/poto/show/2.rss。在控制器的方法中,能够对不同的请求作出应答:
respond_to do |format|
format.html
format.xml {renderRails路由 转摘
            
    
    
        Rails正则表达式REST浏览器ActiveRecordml => @photo.to_xml}
end

5.1 用Http Header指定格式
如作没有:format参数,Rails将自动认为是HTTP Accept格式。

5.2 元类型
默认情况下,Rails能对html, text, json, csv, xml, rss, atom和yaml做出应答。如果还需要其他类型,可以在环境中注册它:
Mime::Type.register "image/jpg", :jpg


6 默认路由
当创建一个Rails应用时,routes.rb就会自动生成两个默认路由:
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
如果你不使用RESTful风格的路由,这个路由为很多URLs就提供了合理的默认值。

7 空路由
不要和默认路由混淆,空路由有它明确的目的:为web站点指定根路径。以example.com为例,以http://example.com或者http://example/来请求,就会由空路由来匹配。

7.1 使用map.root
使用map.root设定空路由:
map.root :controller => 'pages', :action => 'main'使用root方法,是告诉Rails就是请求站点的根路径。

为了更方便阅读, 可以指定一个已经创建好的路由给map.root:
map.index 'index', :controller => 'pages', :action => 'main'
map.root :index

由于是从上至下处理文件,所以必须在调用map.root指定命名路由。

7.2 连接空字符串
也可以使用连接空字符串来指定空路由:
map.connect '', :controller => "pages", :action => "main"

假若指定了空路由,但发现它好像并没有工作,首页还是Rails的默认页面,那么请删除public/index.html文档后再试。

8 检查和测试路由
在应用程序中,路由不应该是个黑盒子,它对你是永远开放的。Rails为检查和测试路由提供了内建的工具。

8.1 用rake查看存的路由
在应用程序中,如果想查看路由列表,可以运行rake routes。它会列出你在routes.rb定义的全部路由。
         users GET /users          {:controller=>"users", :action=>"index"}
formatted_users GET /users.:format {:controller=>"users", :action=>"index"}
                POST /users          {:controller=>"users", :action=>"create"}
                POST /users.:format {:controller=>"users", :action=>"create"}

8.2 测试路由
Rails内建了三个断言来做路由测式
·assert_generates
·assert_recognizes
·assert_routing

8.2.1 assert_generates
使用assert_generates断言一个设置选项生成的特定路径。
assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" }
assert_generates "/about", :controller => "pages", :action => "about"
还可以提供:method参数:

8.2.2 assert_recognizes
assert_recognizes断言反转的assert_generates。在应用程序中它断言Rails认可的给定的路径和路由到一个特定的位置。
assert_recognizes { :controller => "photos", :action => "show", :id => "1" }, "/photos/1"
可以使用:method参数:
assert_recognizes { :controller => "photos", :action => "create" }, { :path => "photos", :method => :post }
能够使用RESTful辅方法测试RESTful路由:
assert_recognizes new_photo_url, { :path => "photos", :method => :post }

8.2.3 assert_routing
assert_routing是断言检测路径生成选项和选项生成路径,它是assert_generates和assert_recognizes的联合:
assert_routing { :path => "photos", :method => :post }, { :controller => "photos", :action => "create" }