routing.textile 31.5 KB
Newer Older
1 2 3 4
h2. Rails Routing from the Outside In

This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to:

5
* Understand the code in +routes.rb+
6
* Construct your own routes, using either the preferred resourceful style or with the <tt>match</tt> method
7
* Identify what parameters to expect an action to receive
8
* Automatically create paths and URLs using route helpers
9
* Use advanced techniques such as constraints and Rack endpoints
10 11 12

endprologue.

13
h3. The Purpose of the Rails Router
14

15
The Rails router recognizes URLs and dispatches them to a controller's action. It can also generate paths and URLs, avoiding the need to hardcode strings in your views.
16 17 18

h4. Connecting URLs to Code

19
When your Rails application receives an incoming request
20

21
<plain>
22
GET /patients/17
23
</plain>
24

25
it asks the router to match it to a controller action. If the first matching route is
26 27

<ruby>
28
match "/patients/:id" => "patients#show"
29 30
</ruby>

31
the request is dispatched to the +patients+ controller's +show+ action with <tt>{ :id => "17" }</tt> in +params+.
32

33
h4. Generating Paths and URLs from Code
34

35
You can also generate paths and URLs. If your application contains this code:
36

37
<ruby>
38
@patient = Patient.find(17)
39 40
</ruby>

41
<erb>
E
eparreno 已提交
42
<%= link_to "Patient Record", patient_path(@patient) %>
43
</erb>
44

E
eparreno 已提交
45
The router will generate the path +/patients/17+. This reduces the brittleness of your view and makes your code easier to understand. Note that the id does not need to be specified in the route helper.
46

47
h3. Resource Routing: the Rails Default
48

49
Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+ actions, a resourceful route declares them in a single line of code.
50

51
h4. Resources on the Web
52

53
Browsers request pages from Rails by making a request for a URL using a specific HTTP method, such as +GET+, +POST+, +PUT+ and +DELETE+. Each method is a request to perform an operation on the resource. A resource route maps a number of related request to the actions in a single controller.
54

55
When your Rails application receives an incoming request for
56

57 58 59
<plain>
DELETE /photos/17
</plain>
60

61
it asks the router to map it to a controller action. If the first matching route is
62 63

<ruby>
64
resources :photos
65 66
</ruby>

67
Rails would dispatch that request to the +destroy+ method on the +photos+ controller with <tt>{ :id => "17" }</tt> in +params+.
68 69 70

h4. CRUD, Verbs, and Actions

71
In Rails, a resourceful route provides a mapping between HTTP verbs and URLs and controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as
72 73

<ruby>
74
resources :photos
75 76
</ruby>

77
creates seven different routes in your application, all mapping to the +Photos+ controller:
78

79
|_. Verb |_.Path            |_.action |_.used for|
80 81 82 83 84 85 86
|GET     |/photos           |index    |display a list of all photos|
|GET     |/photos/new       |new      |return an HTML form for creating a new photo|
|POST    |/photos           |create   |create a new photo|
|GET     |/photos/:id       |show     |display a specific photo|
|GET     |/photos/:id/edit  |edit     |return an HTML form for editing a photo|
|PUT     |/photos/:id       |update   |update a specific photo|
|DELETE  |/photos/:id       |destroy  |delete a specific photo|
87

88
h4. Paths and URLs
89

90
Creating a resourceful route will also expose a number of helpers to the controllers in your application. In the case of +resources :photos+:
91

92 93
* +photos_path+ returns +/photos+
* +new_photo_path+ returns +/photos/new+
94
* +edit_photo_path(id)+ returns +/photos/:id/edit+ (for instance, +edit_photo_path(10)+ returns +/photos/10/edit+)
95
* +photo_path(id)+ returns +/photos/:id+ (for instance, +photo_path(10)+ returns +/photos/10+)
96

97
Each of these helpers has a corresponding +_url+ helper (such as +photos_url+) which returns the same path prefixed with the current host, port and path prefix.
98

99
NOTE: Because the router uses the HTTP verb and URL to match inbound requests, four URLs map to seven different actions.
100 101 102

h4. Defining Multiple Resources at the Same Time

103
If you need to create routes for more than one resource, you can save a bit of typing by defining them all with a single call to +resources+:
104 105

<ruby>
106
resources :photos, :books, :videos
107 108
</ruby>

109
This works exactly the same as
110 111

<ruby>
112 113 114
resources :photos
resources :books
resources :videos
115 116 117 118
</ruby>

h4. Singular Resources

119
Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like +/profile+ to always show the profile of the currently logged in user. In this case, you can use a singular resource to map +/profile+ (rather than +/profile/:id+) to the +show+ action.
120

121 122 123 124 125 126
<ruby>
match "profile" => "users#show"
</ruby>

This resourceful route

127
<ruby>
128
resource :geocoder
129 130
</ruby>

131
creates six different routes in your application, all mapping to the +Geocoders+ controller:
132

133
|_. Verb    |_.Path         |_.action |_.used for|
134 135 136 137 138 139
|GET        |/geocoder/new  |new      |return an HTML form for creating the geocoder|
|POST       |/geocoder      |create   |create the new geocoder|
|GET        |/geocoder      |show     |display the one and only geocoder resource|
|GET        |/geocoder/edit |edit     |return an HTML form for editing the geocoder|
|PUT        |/geocoder      |update   |update the one and only geocoder resource|
|DELETE     |/geocoder      |destroy  |delete the geocoder resource|
140

141
NOTE: Because you might want to use the same controller for a singular route (+/account+) and a plural route (+/accounts/45+), singular resources map to plural controllers.
142

143
A singular resourceful route generates these helpers:
144

145 146 147
* +new_geocoder_path+ returns +/geocoder/new+
* +edit_geocoder_path+ returns +/geocoder/edit+
* +geocoder_path+ returns +/geocoder+
148

149
As with plural resources, the same helpers ending in +_url+ will also include the host, port and path prefix.
150 151 152

h4. Controller Namespaces and Routing

153
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an +Admin::+ namespace. You would place these controllers under the +app/controllers/admin+ directory, and you can group them together in your router:
154 155

<ruby>
156
namespace :admin do
157
  resources :posts, :comments
158 159 160
end
</ruby>

161
This will create a number of routes for each of the +posts+ and +comments+ controller. For +Admin::PostsController+, Rails will create:
162

163
|_. Verb |_.Path               |_.action |_. helper                  |
164 165 166 167 168 169 170
|GET     |/admin/posts        |index    | admin_posts_path         |
|GET     |/admin/posts/new    |new      | new_admin_posts_path     |
|POST    |/admin/posts        |create   | admin_posts_path         |
|GET     |/admin/posts/1      |show     | admin_post_path(id)      |
|GET     |/admin/posts/1/edit |edit     | edit_admin_post_path(id) |
|PUT     |/admin/posts/1      |update   | admin_post_path(id)      |
|DELETE  |/admin/posts/1      |destroy  | admin_post_path(id)      |
171

172
If you want to route +/posts+ (without the prefix +/admin+) to +Admin::PostsController+, you could use
173 174

<ruby>
175 176 177
scope :module => "admin" do
  resources :posts, :comments
end
178 179
</ruby>

180
or, for a single case
181 182

<ruby>
183
resources :posts, :module => "admin"
184 185
</ruby>

186
If you want to route +/admin/posts+ to +PostsController+ (without the +Admin::+ module prefix), you could use
187 188

<ruby>
189 190 191
scope "/admin" do
  resources :posts, :comments
end
192 193
</ruby>

194
or, for a single case
195 196

<ruby>
197
resources :posts, :path => "/admin/posts"
198 199
</ruby>

200
In each of these cases, the named routes remain the same as if you did not use +scope+. In the last case, the following paths map to +PostsController+:
201

202
|_. Verb |_.Path               |_.action |_. helper            |
203 204 205 206 207 208 209
|GET     |/admin/posts        |index    | posts_path         |
|GET     |/admin/posts/new    |new      | posts_path         |
|POST    |/admin/posts        |create   | posts_path         |
|GET     |/admin/posts/1      |show     | post_path(id)      |
|GET     |/admin/posts/1/edit |edit     | edit_post_path(id) |
|PUT     |/admin/posts/1      |update   | post_path(id)      |
|DELETE  |/admin/posts/1      |destroy  | post_path(id)      |
210

211 212 213 214 215 216 217 218 219 220 221 222 223 224
h4. Nested Resources

It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:

<ruby>
class Magazine < ActiveRecord::Base
  has_many :ads
end

class Ad < ActiveRecord::Base
  belongs_to :magazine
end
</ruby>

225
Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration:
226 227

<ruby>
228 229
resources :magazines do
  resources :ads
230 231 232
end
</ruby>

233
In addition to the routes for magazines, this declaration will also route ads to an +AdsController+. The ad URLs require a magazine:
234

235
|_.Verb |_.Path                   |_.action |_.used for|
236 237 238 239 240 241 242
|GET    |/magazines/1/ads         |index    |display a list of all ads for a specific magazine|
|GET    |/magazines/1/ads/new     |new      |return an HTML form for creating a new ad belonging to a specific magazine|
|POST   |/magazines/1/ads         |create   |create a new ad belonging to a specific magazine|
|GET    |/magazines/1/ads/1       |show     |display a specific ad belonging to a specific magazine|
|GET    |/magazines/1/ads/1/edit  |edit     |return an HTML form for editing an ad belonging to a specific magazine|
|PUT    |/magazines/1/ads/1       |update   |update a specific ad belonging to a specific magazine|
|DELETE |/magazines/1/ads/1       |destroy  |delete a specific ad belonging to a specific magazine|
243 244


245
This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+. These helpers take an instance of Magazine as the first parameter (+magazine_ads_url(@magazine)+).
246 247 248 249 250 251

h5. Limits to Nesting

You can nest resources within other nested resources if you like. For example:

<ruby>
252 253 254
resources :publishers do
  resources :magazines do
    resources :photos
255 256 257 258
  end
end
</ruby>

259
Deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize paths such as
260 261 262 263 264 265 266

<pre>
/publishers/1/magazines/2/photos/3
</pre>

The corresponding route helper would be +publisher_magazine_photo_url+, requiring you to specify objects at all three levels. Indeed, this situation is confusing enough that a popular "article":http://weblog.jamisbuck.org/2007/2/5/nesting-resources by Jamis Buck proposes a rule of thumb for good Rails design:

267
TIP: _Resources should never be nested more than 1 level deep._
268

269
h4. Creating Paths and URLs From Objects
270

271
In addition to using the routing helpers, Rails can also create paths and URLs from an array of parameters. For example, suppose you have this set of routes:
272 273

<ruby>
274 275
resources :magazines do
  resources :ads
276 277 278
end
</ruby>

279
When using +magazine_ad_path+, you can pass in instances of +Magazine+ and +Ad+ instead of the numeric IDs.
280

281
<erb>
282
<%= link_to "Ad details", magazine_ad_path(@magazine, @ad) %>
283
</erb>
284

285
You can also use +url_for+ with a set of objects, and Rails will automatically determine which route you want:
286

287 288 289
<erb>
<%= link_to "Ad details", url_for(@magazine, @ad) %>
</erb>
290

291
In this case, Rails will see that +@magazine+ is a +Magazine+ and +@ad+ is an +Ad+ and will therefore use the +magazine_ad_path+ helper. In helpers like +link_to+, you can specify just the object in place of the full +url_for+ call:
292

293 294 295
<erb>
<%= link_to "Ad details", [@magazine, @ad] %>
</erb>
296

297
If you wanted to link to just a magazine, you could leave out the +Array+:
298

299 300 301
<erb>
<%= link_to "Magazine details", @magazine %>
</erb>
302

303
This allows you to treat instances of your models as URLs, and is a key advantage to using the resourceful style.
304 305 306

h4. Adding More RESTful Actions

307
You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional routes that apply to the collection or individual members of the collection.
308 309 310

h5. Adding Member Routes

311
To add a member route, just add a +member+ block into the resource block:
312 313

<ruby>
314 315
resources :photos do
  member do
316
    get 'preview'
317 318
  end
end
319 320
</ruby>

321
This will recognize +/photos/1/preview+ with GET, and route to the +preview+ action of  +PhotosController+. It will also create the +preview_photo_url+ and +preview_photo_path+ helpers.
322

323
Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ routes, you can also pass +:on+ to a route, eliminating the block:
324 325

<ruby>
326
resources :photos do
327
  get 'preview', :on => :member
328
end
329 330 331 332
</ruby>

h5. Adding Collection Routes

333
To add a route to the collection:
334 335

<ruby>
336 337
resources :photos do
  collection do
338
    get 'search'
339 340
  end
end
341 342
</ruby>

343
This will enable Rails to recognize paths such as +/photos/search+ with GET, and route to the +search+ action of +PhotosController+. It will also create the +search_photos_url+ and +search_photos_path+ route helpers.
344

345
Just as with member routes, you can pass +:on+ to a route:
346 347

<ruby>
348
resources :photos do
349
  get 'search', :on => :collection
350
end
351 352 353 354
</ruby>

h5. A Note of Caution

355
If you find yourself adding many extra actions to a resourceful route, it's time to stop and ask yourself whether you're disguising the presence of another resource.
356

357
h3. Non-Resourceful Routes
358

359
In addition to resource routing, Rails has powerful support for routing arbitrary URLs to actions. Here, you don't get groups of routes automatically generated by resourceful routing. Instead, you set up each route within your application separately.
360

361 362 363
While you should usually use resourceful routing, there are still many places where the simpler routing is more appropriate. There's no need to try to shoehorn every last piece of your application into a resourceful framework if that's not a good fit.

In particular, simple routing makes it very easy to map legacy URLs to new Rails actions.
364 365 366 367 368 369

h4. Bound Parameters

When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: +:controller+ maps to the name of a controller in your application, and +:action+ maps to the name of an action within that controller. For example, consider one of the default Rails routes:

<ruby>
370
match ':controller(/:action(/:id))'
371 372
</ruby>

E
eparreno 已提交
373
If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +PhotosController+, and to make the final parameter +"1"+ available as +params[:id]+. This route will also route the incoming request of +/photos+ to +PhotosController#index+, since +:action+ and +:id+ are optional parameters, denoted by parentheses.
374

375
h4. Dynamic Segments
376

377
You can set up as many dynamic segments within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the action as part of +params+. If you set up this route:
378 379

<ruby>
380
match ':controller/:action/:id/:user_id'
381 382
</ruby>

383
An incoming path of +/photos/show/1/2+ will be dispatched to the +show+ action of the +PhotosController+. +params[:id]+ will be +"1"+, and +params[:user_id]+ will be +"2"+.
384

385 386 387 388 389 390
NOTE: You can't use +namespace+ or +:module+ with a +:controller+ path segment. If you need to do this then use a constraint on :controller that matches the namespace you require. e.g:

<ruby>
match ':controller(/:action(/:id))', :controller => /admin\/[^\/]+/
</ruby>

391
h4. Static Segments
392

393
You can specify static segments when creating a route:
394 395

<ruby>
396
match ':controller/:action/:id/with_user/:user_id'
397 398
</ruby>

399
This route would respond to paths such as +/photos/show/1/with_user/2+. In this case, +params+ would be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
400

401
h4. The Query String
402

403
The +params+ will also include any parameters from the query string. For example, with this route:
404 405

<ruby>
406
match ':controller/:action/:id'
407 408
</ruby>

409
An incoming path of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params+ will be <tt>{ :controller => "photos", :action => "show", :id => "1", :user_id => "2" }</tt>.
410 411 412

h4. Defining Defaults

413
You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply them as defaults:
414 415

<ruby>
416
match 'photos/:id' => 'photos#show'
417 418
</ruby>

419
With this route, Rails will match an incoming path of +/photos/12+ to the +show+ action of  +PhotosController+.
420

421
You can also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that you do not specify as dynamic segments. For example:
422 423

<ruby>
424
match 'photos/:id' => 'photos#show', :defaults => { :format => 'jpg' }
425 426
</ruby>

427
Rails would match +photos/12+ to the +show+ action of +PhotosController+, and set +params[:format]+ to +"jpg"+.
428

429
h4. Naming Routes
430

431
You can specify a name for any route using the +:as+ option.
432 433

<ruby>
434
match 'exit' => 'sessions#destroy', :as => :logout
435 436
</ruby>

E
eparreno 已提交
437
This will create +logout_path+ and +logout_url+ as named helpers in your application. Calling +logout_path+ will return +/exit+
438

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
h4. HTTP Verb Constraints

You can use the +:via+ option to constrain the request to one or more HTTP methods:

<ruby>
match 'photos/show' => 'photos#show', :via => :get
</ruby>

There is a shorthand version of this as well:

<ruby>
get 'photos/show'
</ruby>

You can also permit more than one verb to a single route:

<ruby>
match 'photos/show' => 'photos#show', :via => [:get, :post]
</ruby>

459
h4. Segment Constraints
460

461
You can use the +:constraints+ option to enforce a format for a dynamic segment:
462 463

<ruby>
464
match 'photos/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
465 466
</ruby>

467
This route would match paths such as +/photos/A12345+. You can more succinctly express the same route this way:
468 469

<ruby>
470
match 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/
471 472
</ruby>

473 474 475
+:constraints+ takes regular expression. However note that regexp anchors can't be used within constraints. For example following route will not work:

<ruby>
476 477 478 479 480 481 482 483 484 485
match '/:id' => 'posts#show', :constraints => {:id => /^\d/}
</ruby>

However, note that you don't need to use anchors because all routes are anchored at the start.

For example, the following routes would allow for +posts+ with +to_param+ values like +1-hello-world+ that always begin with a number and +users+ with +to_param+ values like +david+ that never begin with a number to share the root namespace:

<ruby>
match '/:id' => 'posts#show', :constraints => { :id => /\d.+/ }
match '/:username' => 'users#show'
486 487
</ruby>

488 489 490 491 492 493 494
h4. Request-Based Constraints

You can also constrain a route based on any method on the <a href="action_controller_overview.html#the-request-object">Request</a> object that returns a +String+.

You specify a request-based constraint the same way that you specify a segment constraint:

<ruby>
495
match "photos", :constraints => {:subdomain => "admin"}
496 497 498 499 500
</ruby>

You can also specify constrains in a block form:

<ruby>
501
namespace :admin do
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
  constraints :subdomain => "admin" do
    resources :photos
  end
end
</ruby>

h4. Advanced Constraints

If you have a more advanced constraint, you can provide an object that responds to +matches?+ that Rails should use. Let's say you wanted to route all users on a blacklist to the +BlacklistController+. You could do:

<ruby>
class BlacklistConstraint
  def initialize
    @ips = Blacklist.retrieve_ips
  end

  def matches?(request)
    @ips.include?(request.remote_ip)
  end
end

TwitterClone::Application.routes.draw do
524
  match "*path" => "blacklist#index",
525 526 527 528
    :constraints => BlacklistConstraint.new
end
</ruby>

529 530 531 532 533
h4. Route Globbing

Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example

<ruby>
534
match 'photos/*other' => 'photos#unknown'
535 536
</ruby>

537
This route would match +photos/12+ or +/photos/long/path/to/12+, setting +params[:other]+ to +"12"+ or +"long/path/to/12"+.
538

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
Wildcard segments do not need to be last in a route. For example

<ruby>
match 'books/*section/:title' => 'books#show'
</ruby>

would match +books/some/section/last-words-a-memoir+ with +params[:section]+ equals +"some/section"+, and +params[:title]+ equals +"last-words-a-memoir"+.

Techincally a route can have even more than one wildard segment indeed, the matcher assigns segments to parameters in an intuitive way. For instance

<ruby>
match '*a/foo/*b' => 'test#index'
</ruby>

would match +zoo/woo/foo/bar/baz+ with +params[:a]+ equals +"zoo/woo"+, and +params[:b]+ equals +"bar/baz"+.

555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
h4. Redirection

You can redirect any path to another path using the +redirect+ helper in your router:

<ruby>
match "/stories" => redirect("/posts")
</ruby>

You can also reuse dynamic segments from the match in the path to redirect to:

<ruby>
match "/stories/:name" => redirect("/posts/%{name}")
</ruby>

You can also provide a block to redirect, which receives the params and (optionally) the request object:
570

571 572 573 574 575 576
<ruby>
match "/stories/:name" => redirect {|params| "/posts/#{params[:name].pluralize}" }
match "/stories" => redirect {|p, req| "/posts/#{req.subdomain}" }
</ruby>

In all of these cases, if you don't provide the leading host (+http://www.example.com+), Rails will take those details from the current request.
577

578
h4. Routing to Rack Applications
579

580
Instead of a String, like +"posts#index"+, which corresponds to the +index+ action in the +PostsController+, you can specify any <a href="rails_on_rack.html">Rack application</a> as the endpoint for a matcher.
581 582

<ruby>
583
match "/application.js" => Sprockets
584 585
</ruby>

586 587 588 589 590 591 592
As long as +Sprockets+ responds to +call+ and returns a <tt>[status, headers, body]</tt>, the router won't know the difference between the Rack application and an action.

NOTE: For the curious, +"posts#index"+ actually expands out to +PostsController.action(:index)+, which returns a valid Rack application.

h4. Using +root+

You can specify what Rails should route +"/"+ to with the +root+ method:
593 594

<ruby>
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
root :to => 'pages#main'
</ruby>

You should put the +root+ route at the end of the file.

h3. Customizing Resourceful Routes

While the default routes and helpers generated by +resources :posts+ will usually serve you well, you may want to customize them in some way. Rails allows you to customize virtually any generic part of the resourceful helpers.

h4. Specifying a Controller to Use

The +:controller+ option lets you explicitly specify a controller to use for the resource. For example:

<ruby>
resources :photos, :controller => "images"
</ruby>

612
will recognize incoming paths beginning with +/photos+ but route to the +Images+ controller:
613

614
|_. Verb |_.Path         |_.action |
615 616 617 618 619 620 621 622
|GET     |/photos        |index    |
|GET     |/photos/new    |new      |
|POST    |/photos        |create   |
|GET     |/photos/1      |show     |
|GET     |/photos/1/edit |edit     |
|PUT     |/photos/1      |update   |
|DELETE  |/photos/1      |destroy  |

623
NOTE: Use +photos_path+, +new_photos_path+, etc. to generate paths for this resource.
624 625 626 627 628 629 630 631 632 633 634

h4. Specifying Constraints

You can use the +:constraints+ option to specify a required format on the implicit +id+. For example:

<ruby>
resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/}
</ruby>

This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, the router would no longer match +/photos/1+ to this route. Instead, +/photos/RR27+ would match.

635
You can specify a single constraint to apply to a number of routes by using the block form:
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653

<ruby>
constraints(:id => /[A-Z][A-Z][0-9]+/) do
  resources :photos
  resources :accounts
end
</ruby>

NOTE: Of course, you can use the more advanced constraints available in non-resourceful routes in this context

h4. Overriding the Named Helpers

The +:as+ option lets you override the normal naming for the named route helpers. For example:

<ruby>
resources :photos, :as => "images"
</ruby>

654
will recognize incoming paths beginning with +/photos+ and route the requests to +PhotosController+:
655

656
|_.HTTP verb|_.Path          |_.action |_.named helper   |
N
Neeraj Singh 已提交
657
|GET        |/photos         |index    | images_path     |
658 659 660 661 662 663 664 665 666
|GET        |/photos/new     |new      | new_image_path  |
|POST       |/photos         |create   | images_path     |
|GET        |/photos/1       |show     | image_path      |
|GET        |/photos/1/edit  |edit     | edit_image_path |
|PUT        |/photos/1       |update   | image_path      |
|DELETE     |/photos/1       |destroy  | image_path      |

h4. Overriding the +new+ and +edit+ Segments

667
The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in paths:
668 669 670 671 672

<ruby>
resources :photos, :path_names => { :new => 'make', :edit => 'change' }
</ruby>

673
This would cause the routing to recognize paths such as
674

W
wycats 已提交
675
<plain>
676 677
/photos/make
/photos/1/change
W
wycats 已提交
678
</plain>
679

680
NOTE: The actual action names aren't changed by this option. The two paths shown would still route to the +new+ and +edit+ actions.
681 682 683 684 685 686

TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can use a scope:

<ruby>
scope :path_names => { :new => "make" } do
  # rest of your routes
687 688 689
end
</ruby>

690
h4. Prefixing the Named Route Helpers
691

692
You can use the +:as+ option to prefix the named route helpers that Rails generates for a route. Use this option to prevent name collisions between routes using a path scope.
693

694 695
<ruby>
scope "admin" do
696
  resources :photos, :as => "admin_photos"
697
end
698

699 700 701
resources :photos
</ruby>

702
This will provide route helpers such as +admin_photos_path+, +new_admin_photo_path+ etc.
703

704
To prefix a group of routes, use +:as+ with +scope+:
705 706

<ruby>
707
scope "admin", :as => "admin" do
708 709 710 711
  resources :photos, :accounts
end

resources :photos, :accounts
712 713
</ruby>

714
NOTE: The +namespace+ scope will automatically add +:as+ as well as +:module+ and +:path+ prefixes.
715 716

h4. Restricting the Routes Created
717

718
By default, Rails creates routes for all seven of the default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the +:only+ and +:except+ options to fine-tune this behavior. The +:only+ option tells Rails to create only the specified routes:
719 720

<ruby>
721
resources :photos, :only => [:index, :show]
722 723
</ruby>

724 725 726
Now, a +GET+ request to +/photos+ would succeed, but a +POST+ request to +/photos+ (which would ordinarily be routed to the +create+ action) will fail.

The +:except+ option specifies a route or list of routes that Rails should _not_ create:
727

728 729 730
<ruby>
resources :photos, :except => :destroy
</ruby>
731

732
In this case, Rails will create all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/:id+).
733

734
TIP: If your application has many RESTful routes, using +:only+ and +:except+ to generate only the routes that you actually need can cut down on memory use and speed up the routing process.
735

736
h4. Translated Paths
737

738
Using +scope+, we can alter path names generated by resources:
739 740

<ruby>
741 742 743
scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do
  resources :categories, :path => "kategorien"
end
744 745
</ruby>

746
Rails now creates routes to the +CategoriesController+.
747

748
|_.HTTP verb|_.Path                     |_.action |
749 750 751 752 753 754 755
|GET        |/kategorien                |index    |
|GET        |/kategorien/neu            |new      |
|POST       |/kategorien                |create   |
|GET        |/kategorien/1              |show     |
|GET        |/kategorien/:id/bearbeiten |edit     |
|PUT        |/kategorien/1              |update   |
|DELETE     |/kategorien/1              |destroy  |
756

757
h4. Overriding the Singular Form
758

759
If you want to define the singular form of a resource, you should add additional rules to the +Inflector+.
760 761

<ruby>
762 763 764
ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'tooth', 'teeth'
end
765 766
</ruby>

767
h4(#nested-names). Using +:as+ in Nested Resources
768

769
The +:as+ option overrides the automatically-generated name for the resource in nested route helpers. For example,
770 771 772

<ruby>
resources :magazines do
773
  resources :ads, :as => 'periodical_ads'
774
end
775 776
</ruby>

777
This will create routing helpers such as +magazine_periodical_ads_url+ and +edit_magazine_periodical_ad_path+.
778 779 780

h3. Inspecting and Testing Routes

781
Rails offers facilities for inspecting and testing your routes.
782

783
h4. Seeing Existing Routes with +rake+
784

785
If you want a complete list of all of the available routes in your application, run +rake routes+ command. This will print all of your routes, in the same order that they appear in +routes.rb+. For each route, you'll see:
786 787 788

* The route name (if any)
* The HTTP verb used (if the route doesn't respond to all verbs)
789 790
* The URL pattern to match
* The routing parameters for the route
791 792 793 794 795 796 797 798 799 800

For example, here's a small section of the +rake routes+ output for a RESTful route:

<pre>
          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"}
</pre>

801 802 803
You may restrict the listing to the routes that map to a particular controller setting the +CONTROLLER+ environment variable:

<shell>
804
$ CONTROLLER=users rake routes
805 806
</shell>

807 808 809 810
TIP: You'll find that the output from +rake routes+ is much more readable if you widen your terminal window until the output lines don't wrap.

h4. Testing Routes

811
Routes should be included in your testing strategy (just like the rest of your application). Rails offers three "built-in assertions":http://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html designed to make testing routes simpler:
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830

* +assert_generates+
* +assert_recognizes+
* +assert_routing+

h5. The +assert_generates+ Assertion

Use +assert_generates+ to assert that a particular set of options generate a particular path. You can use this with default routes or custom routes

<ruby>
assert_generates "/photos/1", { :controller => "photos", :action => "show", :id => "1" }
assert_generates "/about", :controller => "pages", :action => "about"
</ruby>

h5. The +assert_recognizes+ Assertion

The +assert_recognizes+ assertion is the inverse of +assert_generates+. It asserts that Rails recognizes the given path and routes it to a particular spot in your application.

<ruby>
831
assert_recognizes({ :controller => "photos", :action => "show", :id => "1" }, "/photos/1")
832 833 834 835 836
</ruby>

You can supply a +:method+ argument to specify the HTTP verb:

<ruby>
837
assert_recognizes({ :controller => "photos", :action => "create" }, { :path => "photos", :method => :post })
838 839
</ruby>

840
You can also use the resourceful helpers to test recognition of a RESTful route:
841 842 843 844 845 846 847 848 849 850

<ruby>
assert_recognizes new_photo_url, { :path => "photos", :method => :post }
</ruby>

h5. The +assert_routing+ Assertion

The +assert_routing+ assertion checks the route both ways: it tests that the path generates the options, and that the options generate the path. Thus, it combines the functions of +assert_generates+ and +assert_recognizes+.

<ruby>
851
assert_routing({ :path => "photos", :method => :post }, { :controller => "photos", :action => "create" })
852 853 854 855
</ruby>

h3. Changelog

W
wycats 已提交
856
* April 10, 2010: Updated guide to remove outdated and superfluous information, and to provide information about new features, by "Yehuda Katz":http://www.yehudakatz.com
857
* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by "Rizwan Reza":http://www.rizwanreza.com/
858
* Febuary 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist
859
* October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy
860 861
* September 23, 2008: Added section on namespaced controllers and routing, by "Mike Gunderloy":credits.html#mgunderloy
* September 10, 2008: initial version by "Mike Gunderloy":credits.html#mgunderloy