rails routes 详解

Rails Routes控制台测试

 cd RubyOnRails/app/path cd script/console> rs = ActionController::Routing::Routes> puts rs.routesANY /:controller/service.wsdl/ {:action=>"wsdl"}ANY /:controller/:action/:id.:format/ {}ANY /:controller/:action/:id/ {}=>nil

修改config/routes.rb文件,添加一行

map.connect 'modules/controller/:action/*other', :controller => 'modules/controller'

回到console

> rs.reload> puts rs.routesANY /:controller/service.wsdl/ {:action=>"wsdl"}ANY /:controller/:action/:id.:format/ {}ANY /:controller/:action/:id/ {}ANY /modules/controller/:action/:other/ {:controller=>"modules/controller"}=>nil> rs.recognize_path '/modules/controller/test/2?x=1'=> {:action=>"test", :other=>["2?x=1"], :controller=>"modules/controller"}> rs.recognize_path '/test/action/1'=> {:action=>"action", :id=>"1", :controller=>"test"}> rs.add_route('/x/y/z', {:controller => 'test', :action => 'index', :id => 0})=> >puts rs.routesANY /:controller/service.wsdl/ {:action=>"wsdl"}ANY /:controller/:action/:id.:format/ {}ANY /:controller/:action/:id/ {}ANY /modules/controller/:action/:other/ {:controller=>"modules/controller"}ANY /x/y/z/ {:action=>"index", :id=>0, :controller=>"test"}=> nil> rs.draw do |map|?> map.connect '/blog/:id', :controller => 'blog', :action => 'list'> end=> [ActionController::Base, ActionView::Base]> puts rs.routesANY /blog/:id/ {:action=>"list", :controller=>"blog"}=> nil> rs.recognize_path '/blog/1'=> {:action=>"list", :id=>"1", :controller=>"blog"}

这里发现原来的routes全部不见了,只有这个新建的routes了,因为draw方法内部实现为:

def draw    clear!    yield Mapper.new(self)    named_routes.installend

draw方法块里的map对象里method_missing方法就是用来实现具名路由named routes的。先看下源码如下:

def method_missing(route_name, *args, &proc)  super unless args.length >= 1 && proc.nil?  @set.add_named_route(route_name, *args)end

上面对实例变量@set就是前面的rs对象,那么就看一下rs.add_named_route方法吧

> rs.clear!> rs.add_named_route('index', 'user/index', :controller => 'user', :action => 'index')puts rs.named_routes#=> nil> puts rs.routesANY /user/index/ {:action=>"index", :controller=>"user"}=> nil> puts rs.named_routes.routesindexANY /user/index/ {:action=>"index", :controller=>"user"}=> nil

定义了具名路后就可以在controller/view中像url_for一样调用,只要在route name后面加上_url就可以,url_for在console里不能调试,可以用rs.generate(request)方法测试。

# In addition to providing url_for, named routes are also accessible after including UrlWriter.url_for(:controller => 'signup', action => 'index', :token => token)index_url(:id => 1)#=> http://localhost/user/index?id=1> rs.generate(:controller => 'test', :action => 'index', :id => 3)=> "/test/index/3"

另外在map这个对象里有个方法root可以给根目录定义路径,用法如下:

> rs.draw do |map|?>   map.root :controller => 'test', :action => 'list'> endArgumentError: Illegal route: the :controller must be specified!        from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:965:in `build'        from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1172:in `add_route'        from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1178:in `add_named_route'        from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:997:in `root_without_deprecation'        from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/deprecation.rb:94:in `root'        from (irb):60        from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1139:in `draw'        from (irb):59# Added deprecation notice for anyone who already added a named route called "root".# It'll be used as a shortcut for map.connect '' in Rails 2.0.# def root(*args, &proc)#   super unless args.length >= 1 && proc.nil?#   @set.add_named_route("root", *args)# end# deprecate :root => "(as the the label for a named route) will become a shortcut for map.connect '', so find another name"

Rails2.0才会引进此方法,所以Rails建议用户不要使用此具名路由,如下:

> rs.draw do |map|?> map.root '', :controller => 'test', :action => 'list'> end=> [ActionController::Base, ActionView::Base]> puts rs.routesANY / {:action=>"list", :controller=>"test"}=> nil> puts rs.named_routes.routesrootANY / {:action=>"list", :controller=>"test"}=> nil

这个写法其实就是做了个具名路由,而不是调用map.root方法,调用的是method_missing方法。