、 路由规则
1 路由文件
config/routes.rb 文件建立了外部请求与应用程序的连接
2 路由设置查看
应用程序路由定义在 RoutSet 对象中,该对象保存在 ActionController::Routing 模块的常量 Routes 中,在 console 中通过 ActionController::Routing::Routes.routes 方法可以访问到 . (为了简单后面用变量 rs )
3 给定 URL 查看路由文件中是否有相应的配置
rs.recognize_path “/xxxx” 若有此配置则 =>{….}
4 给定任意参数查看所生成的 URL
rs.generate(:controller=>:xxx,:action=>:yyy………)
5 把尚未编写出的控制器加入路由配置
ActionController::Routing::use_controllers! [“xxx”,”yyy”,”zzz”]
注意:用 rails 框架可一同生成路由和控制器
6 重新装载路由定义
在 console 中执行 load ”config/routes.rb” 一般在执行 5 后做此操作
二、 用 map.connect 定义路由规则
1 规则( map.connect 的主要参数在‘‘中)
路由中 map.connect ‘ 期中设置规则 ’ 如 map.connect ‘:controller/:action/:id’
注意:
1) 配置中以 :xxxx 形式的部分将得到 URL 中对应的值,形成键 - 值的 hash 参数,如 xiaofeng/nb/1 这个 URL 中的 xiaofeng 将成为键 :controller 的值, nb 也一样
2) 配置中以 *xxxx 形式的部分将得到 URL 对应部分以后的所有值,与 :xxxx 模式类似,不过 *xxxx 的位置始终在路由配置的最后 如 ’:controller/:action/*xxxx’ 与此同时 *xxxx 得到的将是一个 hash 而不只是一个值
3) 主要参数中的非 :xxxx 形式与 *xxxx 形式当且仅当 URL 中与之对应时才会匹配上,如‘ story/:controller/:id ’与之匹配的 URL 必须第一个字段为 story
4) :controller 与 :action 可以出现在主要参数的单引号中,也可以出现在下面将要介绍的其他参数中,以 hash 的形式来指定他们所对应的值
5) 对 URL 匹配对应的路由时会根据 routes.rb 中声明的顺序逐一匹配,并使用第一条符合的路由规则
2 map.connect 接受的另一些参数(除 :controller 和 :action )
1) :defaults=>{:name=>’value’, …… }
为模式中命名参数设置默认值。如果一个模式的组成部分有默认值,可以在 URL 中省略。 Routing 下默认提供了 defaults=>{:action=”index”,:id=>nil}
2) :requirements=>{:name=>/regexp/, …… }
特定组成部分必须与指定的正则表达式一一匹配
3) :conditions=>{:name=>/regexp/orstring , …… }
该参数指定请求的动词,如 :conditions=>{:method=>:get},
4) :name=>value
设置 :name 参数的默认值,与 :defaults 的区别为其指定的 :name 的默认值对主要参数部分有此 :name 的路由模式不起作用( :name 的值以 URL 中给定的值为准则),除非 URL 中没有给定对应的值并且 :defaults 没有指定其默认值时此参数有效
一般情况下有 :name=>value 指定的参数为定死的,而不是路由给出的
三、 生成 URL
1 无名路由
url_for() 方法
接受一组 hash 并将其转化为 URL 地址
如: url_for(:controller=>’store’, :action=>’display’, :id=>’123’)
解析为 http://pragprog.com/store/display/123
当接受参数中有部分参数被省略时,被省略的参数的值有当前控制器对应的值代替
如:当前 URL 为 http://pragprog.com/store/display
url_for(:action=>’show’) # URL =>http://pragprog.com/store/show
被省略的 controller 被当前 controller 所代替了
当接受参数中使用 ActiveRecord 的对象作为参数时,则使用该对象数据库中的 id 值
如: user=User.find(1)
redirect_to(:action=>’show’, :id=>user) # => /show/1
在控制器中动态改变服务器的默认配置 default_url_options()
接受参数:见 P403
2 具名路由
既给 routes.rb 中的路由配置起名,可以通过访问“名称 _url ”来访问该路由配置
如: map.index “blog/”, :controller=>”blog”, :action=>”index”
index_url # => http://pragprog.com/blog/
可以通过接受参数为具名路由传入 URL 参数
如: map.show “blog/:id”, :controller=>”blog”, :action=>”show”
show_url :id=>”1” # => http://pragprog.com/blog/1
注: 定义的具名路由除了用 xxx_url 外还可以用 xxx_path (不包含 xxx_url 中的协议、主机地址和端口,只包含路径)
3 有根路由
对于同一应用的开发和生产版本放到同一服务器上可以使用有根路由来区别不同应用下的相同功能
如:同一应用的 blog 控制器在不同版本下的路由为
http://megablogworld.com/development/blog 开发模式
http://megablogworld.com/project/blog 生产模式
设置有根路由:
1 在服务器配置文件中设置环境变量 RAILS_RELATIVE_URL_ROOT
2 在 config/environments.rb 文件中, 通过设置环境变量 ENV[‘RAILS_RELATIVE_URL_ROOT’] 或 ActionController::AbstractRequest.relative_url_root = "/other_url"
4 REST 和 Rails
Rails 支持增加一组 REST 风格的路由配置的接口:在 route 文件中设置
map.resources:articlesjiang 控制器的路由将以 rest 风格来匹配 URL
Method |
URL path |
Action |
Helper |
get |
/articles |
index |
articles_url |
post |
/articles |
create |
articles_url |
Get |
/articles |
new |
new_article_url |
Get |
/articles/1 |
show |
article_url(:id=>1) |
Put |
/articles/1 |
update |
article_url(:id=>1) |
Get |
/articles/1;edit |
edit |
edit_article_url(:id=>1) |
Delete |
/articles/1 |
destroy |
article_url(:id=>1) |
5 为 rest 添加自己的 Action
添加一个为一组资源提供的 action
map.resources:articles, :controller => {:recent => :get}
Method |
URL path |
Action |
Helper |
get |
/articles;recent |
recent |
recent_articles_url |
为某项资源添加一个 action
map.resources:articles, :member => {:embargo => :put, :release => :put}
Method |
URL path |
Action |
Helper |
put |
/articles/1;embargo |
embargo |
dmbargo_article_url(:id=>1) |
put |
/articles/1;release |
release |
release_article_url(:id=>1) |
只针对 action=>:new 来添加一个 action
map.resources:articles, :new => {:shot => :put,}
Method |
URL path |
Action |
Helper |
put |
/articles/new;shot |
shot |
shot_new_article_url(:id=>1) |
6 rest 嵌套资源
声明嵌套资源路由
map.resources :articles do |article|
article.resources :comments
end
Method |
URL path |
Action |
Helper |
get |
/articles/1/comments |
index |
comments_url(:article_id=>1) |
post |
/articles/1/comments |
create |
comments_url(:article_id=>1) |
Get |
/articles/1/comments/new |
new |
new_comments_url(:article_id=>1) |
Get |
/articles/1/comments/99 |
show |
comments_url(:article_id=>1,:id=>99) |
Put |
/articles/1/comments/99 |
update |
comments_url(:article_id=>1,:id=>99) |
Get |
/articles/1/comments/99;edit |
edit |
edit_comments_url(:article_id=>1,:id=>99) |
Delete |
/articles/1/comments/99 |
destroy |
comments_url(:article_id=>1,:id=>99) |
7 选择数据表现形式( respond_to )
非 rest 风格的路由设置
map.store “/store/:action/:id.:format”, :id=>nil, :format=>nil
在控制器中用代码快如 action 中 show 控制器
def show
respond_to do |format|
format.html
format.xml {render :xml => @product.to_xml }
format.yaml { render :text => @product.to_yaml }
end
end
针对 /store/show/1.html, /store/show/1.xml, /store/show/1.yaml 将返回相应格式的内容
Rest 风格的路由设置
map.resources 所指定的路由规则默认开启了这项功能
8 路由测试
断言指定选项会生成指定的路径
assert_generates(“/store”, :controller => “store”, :action => “index”)
断言给定的路径,路由将分析成一个 hash
Assert_recognizes({“controller”=>”store”, “action”=>”index”}, “/store”)
将上述两个断言结合起来即正向检查又反相检查
Assert_routing(“/store”, :controller =>”store”, :action => “index”)