| | 50 | # == Routing |
|---|
| | 51 | # |
|---|
| | 52 | # The routing module provides URL rewriting in native Ruby. It's a way to |
|---|
| | 53 | # redirect incoming requests to controllers and actions. This replaces |
|---|
| | 54 | # mod_rewrite rules. Best of all Rails' Routing works with any web server. |
|---|
| | 55 | # Routes are defined in routes.rb in your RAILS_ROOT/config directory. |
|---|
| | 56 | # |
|---|
| | 57 | # Consider the following route, installed by Rails when you generate your |
|---|
| | 58 | # application: |
|---|
| | 59 | # |
|---|
| | 60 | # map.connect ':controller/:action/:id' |
|---|
| | 61 | # |
|---|
| | 62 | # This route states that it expects requests to consist of a |
|---|
| | 63 | # :controller followed by an :action that in turns is fed by some :id |
|---|
| | 64 | # |
|---|
| | 65 | # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end up |
|---|
| | 66 | # with: |
|---|
| | 67 | # |
|---|
| | 68 | # params = { :controller => 'blog', |
|---|
| | 69 | # :action => 'edit' |
|---|
| | 70 | # :id => '22' |
|---|
| | 71 | # } |
|---|
| | 72 | # |
|---|
| | 73 | # Think of creating routes as drawing a map for your requests. The map tells |
|---|
| | 74 | # them where to go based on some predefined pattern: |
|---|
| | 75 | # |
|---|
| | 76 | # ActionController::Routing::Routes.draw do |map| |
|---|
| | 77 | # Pattern 1 tells some request to go to one place |
|---|
| | 78 | # Pattern 2 tell them to go to another |
|---|
| | 79 | # ... |
|---|
| | 80 | # end |
|---|
| | 81 | # |
|---|
| | 82 | # The following symbols are special: |
|---|
| | 83 | # |
|---|
| | 84 | # :controller maps to your controller name |
|---|
| | 85 | # :action maps to an action with your controllers |
|---|
| | 86 | # |
|---|
| | 87 | # Other names simply map to a parameter as in the case of +:id+. |
|---|
| | 88 | # |
|---|
| | 89 | # == Route priority |
|---|
| | 90 | # |
|---|
| | 91 | # Not all routes are created equally. Routes have priority defined by the |
|---|
| | 92 | # order of appearance of the routes in the routes.rb file. The priority goes |
|---|
| | 93 | # from top to bottom. The last route in that file is at the lowest priority |
|---|
| | 94 | # will be applied last. If no route matches, 404 is returned. |
|---|
| | 95 | # |
|---|
| | 96 | # Within blocks, the empty pattern goes first i.e. is at the highest priority. |
|---|
| | 97 | # In practice this works out nicely: |
|---|
| | 98 | # |
|---|
| | 99 | # ActionController::Routing::Routes.draw do |map| |
|---|
| | 100 | # map.with_options :controller => 'blog' do |blog| |
|---|
| | 101 | # blog.show '', :action => 'list' |
|---|
| | 102 | # end |
|---|
| | 103 | # map.connect ':controller/:action/:view |
|---|
| | 104 | # end |
|---|
| | 105 | # |
|---|
| | 106 | # In this case, invoking blog controller (with an URL like '/blog/') |
|---|
| | 107 | # without parameters will activate the 'list' action by default. |
|---|
| | 108 | # |
|---|
| | 109 | # == Defaults routes and default parameters |
|---|
| | 110 | # |
|---|
| | 111 | # Setting a default route is straightforward in Rails because by appending a |
|---|
| | 112 | # Hash to the end of your mapping you can set default parameters. |
|---|
| | 113 | # |
|---|
| | 114 | # Example: |
|---|
| | 115 | # ActionController::Routing:Routes.draw do |map| |
|---|
| | 116 | # map.connect ':controller/:action/:id', :controller => 'blog' |
|---|
| | 117 | # end |
|---|
| | 118 | # |
|---|
| | 119 | # This sets up +blog+ as the default controller if no other is specified. |
|---|
| | 120 | # This means visiting '/' would invoke the blog controller. |
|---|
| | 121 | # |
|---|
| | 122 | # More formally, you can define defaults in a route with the +:defaults+ key. |
|---|
| | 123 | # |
|---|
| | 124 | # map.connect ':controller/:id/:action', :action => 'show', :defaults => { :page => 'Dashboard' } |
|---|
| | 125 | # |
|---|
| | 126 | # == Named routes |
|---|
| | 127 | # |
|---|
| | 128 | # Routes can be named with the syntax <tt>map.name_of_route options</tt>, |
|---|
| | 129 | # allowing for easy reference within your source as +name_of_route_url+. |
|---|
| | 130 | # |
|---|
| | 131 | # Example: |
|---|
| | 132 | # # In routes.rb |
|---|
| | 133 | # map.login 'login', :controller => 'accounts', :action => 'login' |
|---|
| | 134 | # |
|---|
| | 135 | # # With render, redirect_to, tests, etc. |
|---|
| | 136 | # redirect_to login_url |
|---|
| | 137 | # |
|---|
| | 138 | # Arguments can be passed as well. |
|---|
| | 139 | # |
|---|
| | 140 | # redirect_to show_item_url(:id => 25) |
|---|
| | 141 | # |
|---|
| | 142 | # When using +with_options+, the name goes after the item passed to the block. |
|---|
| | 143 | # |
|---|
| | 144 | # ActionController::Routing::Routes.draw do |map| |
|---|
| | 145 | # map.with_options :controller => 'blog' do |blog| |
|---|
| | 146 | # blog.show '', :action => 'list' |
|---|
| | 147 | # blog.delete 'delete/:id', :action => 'delete', |
|---|
| | 148 | # blog.edit 'edit/:id', :action => 'edit' |
|---|
| | 149 | # end |
|---|
| | 150 | # map.connect ':controller/:action/:view |
|---|
| | 151 | # end |
|---|
| | 152 | # |
|---|
| | 153 | # You would then use the named routes in your views: |
|---|
| | 154 | # |
|---|
| | 155 | # link_to @article.title, show_url(:id => @article.id) |
|---|
| | 156 | # |
|---|
| | 157 | # == Pretty URL's |
|---|
| | 158 | # |
|---|
| | 159 | # Routes can generate pretty URLs. For example: |
|---|
| | 160 | # |
|---|
| | 161 | # map.connect 'articles/:year/:month/:day', |
|---|
| | 162 | # :controller => 'articles', |
|---|
| | 163 | # :action => 'find_by_date', |
|---|
| | 164 | # :year => /\d{4}/, |
|---|
| | 165 | # :month => /\d{1,2}/, |
|---|
| | 166 | # :day => /\d{1,2}/ |
|---|
| | 167 | # |
|---|
| | 168 | # # Using the route above, the url below maps to: |
|---|
| | 169 | # # params = {:year => '2005', :month => '11', :day => '06'} |
|---|
| | 170 | # # http://localhost:3000/articles/2005/11/06 |
|---|
| | 171 | # |
|---|
| | 172 | # == Regular Expressions and parameters |
|---|
| | 173 | # You can specify a reqular expression to define a format for a parameter. |
|---|
| | 174 | # |
|---|
| | 175 | # map.geocode 'geocode/:postalcode', :controller => 'geocode', |
|---|
| | 176 | # :action => 'show', :postalcode => /\d{5}(-\d{4})?/ |
|---|
| | 177 | # |
|---|
| | 178 | # or more formally: |
|---|
| | 179 | # |
|---|
| | 180 | # map.geocode 'geocode/:postalcode', :controller => 'geocode', |
|---|
| | 181 | # :action => 'show', |
|---|
| | 182 | # :requirements { :postalcode => /\d{5}(-\d{4})?/ } |
|---|
| | 183 | # |
|---|
| | 184 | # == Route globbing |
|---|
| | 185 | # |
|---|
| | 186 | # Specifying <tt>*[string]</tt> as part of a rule like : |
|---|
| | 187 | # |
|---|
| | 188 | # map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?' |
|---|
| | 189 | # |
|---|
| | 190 | # will glob all remaining parts of the route that were not recognized earlier. This idiom must appear at the end of the path. The globbed values are in <tt>params[:path]</tt> in this case. |
|---|
| | 191 | # |
|---|
| | 192 | # == Reloading routes |
|---|
| | 193 | # |
|---|
| | 194 | # You can reload routes if you feel you must: |
|---|
| | 195 | # |
|---|
| | 196 | # Action::Controller::Routes.reload |
|---|
| | 197 | # |
|---|
| | 198 | # This will clear all named routes and reload routes.rb |
|---|
| | 199 | # |
|---|
| | 200 | # == Testing Routes |
|---|
| | 201 | # |
|---|
| | 202 | # The two main methods for testing your routes: |
|---|
| | 203 | # |
|---|
| | 204 | # === +assert_routing+ |
|---|
| | 205 | # |
|---|
| | 206 | # def test_movie_route_properly_splits |
|---|
| | 207 | # opts = {:controller => "plugin", :action => "checkout", :id => "2"} |
|---|
| | 208 | # assert_routing "plugin/checkout/2", opts |
|---|
| | 209 | # end |
|---|
| | 210 | # |
|---|
| | 211 | # +assert_routing+ lets you test whether or not the route properly resolves into options. |
|---|
| | 212 | # |
|---|
| | 213 | # === +assert_recognizes+ |
|---|
| | 214 | # |
|---|
| | 215 | # def test_route_has_options |
|---|
| | 216 | # opts = {:controller => "plugin", :action => "show", :id => "12"} |
|---|
| | 217 | # assert_recognizes opts, "/plugins/show/12" |
|---|
| | 218 | # end |
|---|
| | 219 | # |
|---|
| | 220 | # Note the subtle difference between the two: +assert_routing+ tests that |
|---|
| | 221 | # an URL fits options while +assert_recognizes+ tests that an URL |
|---|
| | 222 | # breaks into parameters properly. |
|---|
| | 223 | # |
|---|
| | 224 | # In tests you can simply pass the URL or named route to +get+ or +post+. |
|---|
| | 225 | # |
|---|
| | 226 | # def send_to_jail |
|---|
| | 227 | # get '/jail' |
|---|
| | 228 | # assert_response :success |
|---|
| | 229 | # assert_template "jail/front" |
|---|
| | 230 | # end |
|---|
| | 231 | # |
|---|
| | 232 | # def goes_to_login |
|---|
| | 233 | # get login_url |
|---|
| | 234 | # #... |
|---|
| | 235 | # end |
|---|
| | 236 | # |
|---|