diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2008-10-05 22:16:26 +0100 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2008-10-05 22:16:26 +0100 |
commit | a2932784bb71e72a78c32819ebd7ed2bed551e3e (patch) | |
tree | 99bfd589a48153e33f19ae72baa6e98f5708a9b8 /railties/doc/guides/routing/routing_outside_in.txt | |
parent | 4df45d86097efbeabceecfe53d8ea2da9ccbb107 (diff) | |
download | rails-a2932784bb71e72a78c32819ebd7ed2bed551e3e.tar.gz rails-a2932784bb71e72a78c32819ebd7ed2bed551e3e.tar.bz2 rails-a2932784bb71e72a78c32819ebd7ed2bed551e3e.zip |
Merge docrails
Diffstat (limited to 'railties/doc/guides/routing/routing_outside_in.txt')
-rw-r--r-- | railties/doc/guides/routing/routing_outside_in.txt | 119 |
1 files changed, 101 insertions, 18 deletions
diff --git a/railties/doc/guides/routing/routing_outside_in.txt b/railties/doc/guides/routing/routing_outside_in.txt index bc08b107cf..f35ac0cebd 100644 --- a/railties/doc/guides/routing/routing_outside_in.txt +++ b/railties/doc/guides/routing/routing_outside_in.txt @@ -17,7 +17,7 @@ Rails routing is a two-way piece of machinery - rather as if you could turn tree When your Rails application receives an incoming HTTP request, say ------------------------------------------------------- -GET /patient/17 +GET /patients/17 ------------------------------------------------------- the routing engine within Rails is the piece of code that dispatches the request to the appropriate spot in your application. In this case, the application would most likely end up running the +show+ action within the +patients+ controller, displaying the details of the patient whose ID is 17. @@ -32,7 +32,7 @@ Routing also works in reverse. If your application contains this code: <%= link_to "Patient Record", patient_path(@patient) %> ------------------------------------------------------- -Then the routing engine is the piece that translates that to a link to a URL such as +http://example.com/patient/17+. By using routing in this way, you can reduce the brittleness of your application as compared to one with hard-coded URLs, and make your code easier to read and understand. +Then the routing engine is the piece that translates that to a link to a URL such as +http://example.com/patients/17+. By using routing in this way, you can reduce the brittleness of your application as compared to one with hard-coded URLs, and make your code easier to read and understand. NOTE: Patient needs to be declared as a resource for this style of translation via a named route to be available. @@ -168,6 +168,24 @@ photos_url # => "http://www.example.com/photos" photos_path # => "/photos" ------------------------------------------------------- +=== Defining Multiple Resources at the Same Time + +If you need to create routes for more than one RESTful resource, you can save a bit of typing by defining them all with a single call to +map.resources+: + +[source, ruby] +------------------------------------------------------- +map.resources :photos, :books, :videos +------------------------------------------------------- + +This has exactly the same effect as + +[source, ruby] +------------------------------------------------------- +map.resources :photos +map.resources :books +map.resources :videos +------------------------------------------------------- + === Singular Resources You can also apply RESTful routing to singleton resources within your application. In this case, you use +map.resource+ instead of +map.resources+ and the route generation is slightly different. For example, a routing entry of @@ -177,7 +195,7 @@ You can also apply RESTful routing to singleton resources within your applicatio map.resource :geocoder ------------------------------------------------------- -creates seven different routes in your application: +creates six different routes in your application: [grid="all"] `----------`---------------`-----------`--------`------------------------------------------- @@ -238,7 +256,20 @@ PUT /photos/1 Images update update a specific image DELETE /photos/1 Images destroy delete a specific image -------------------------------------------------------------------------------------------- -NOTE: The helpers will be generated with the name of the resource, not the name of the controller. So in this case, you'd still get +photos_path+, +photos_new_path+, and so on. +NOTE: The helpers will be generated with the name of the resource, not the name of the controller. So in this case, you'd still get +photos_path+, +new_photo_path+, and so on. + +=== Controller Namespaces and Routing === + +Rails allows you to group your controllers into namespaces by saving them in folders underneath +app/controllers+. The +:controller+ option provides a convenient way to use these routes. For example, you might have a resource whose controller is purely for admin users in the +admin+ folder: + +[source, ruby] +------------------------------------------------------- +map.resources :adminphotos, :controller => "admin/photos" +------------------------------------------------------- + +If you use controller namespaces, you need to be aware of a subtlety in the Rails routing code: it always tries to preserve as much of the namespace from the previous request as possible. For example, if you are on a view generated from the +adminphoto_path+ helper, and you follow a link generated with +<%= link_to "show", adminphoto(1) %> you will end up on the view generated by +admin/photos/show+ but you will also end up in the same place if you have +<%= link_to "show", {:controller => "photos", :action => "show"} %>+ because Rails will generate the show URL relative to the current URL. + +TIP: If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: +<%= link_to "show", {:controller => "/photos", :action => "show"} %>+ ==== Using :singular @@ -290,7 +321,7 @@ PUT /images/1 Photos update update a specific photo DELETE /images/1 Photos destroy delete a specific photo -------------------------------------------------------------------------------------------- -NOTE: The helpers will be generated with the name of the resource, not the path name. So in this case, you'd still get +photos_path+, +photos_new_path+, and so on. +NOTE: The helpers will be generated with the name of the resource, not the path name. So in this case, you'd still get +photos_path+, +new_photo_path+, and so on. ==== Using :path_names @@ -345,7 +376,7 @@ map.resources :photos, :path_prefix => '/photographers/:photographer_id', :name_ map.resources :photos, :path_prefix => '/agencies/:agency_id', :name_prefix => 'agency_' ------------------------------------------------------- -This combination will give you route helpers such as +photographer_photos_path+ and +agency_photo_edit_path+ to use in your code. +This combination will give you route helpers such as +photographer_photos_path+ and +agency_edit_photo_path+ to use in your code. === Nested Resources @@ -379,11 +410,11 @@ 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 photo belonging to a specific magazine -GET /magazines/1/ads/1 Ads show display a specific photo belonging to a specific magazine -GET /magazines/1/ads/1/edit Ads edit return an HTML form for editing a photo belonging to a specific magazine -PUT /magazines/1/ads/1 Ads update update a specific photo belonging to a specific magazine -DELETE /magazines/1/ads/1 Ads destroy delete a specific photo 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 -------------------------------------------------------------------------------------------- This will also create routing helpers such as +magazine_ads_url+ and +magazine_edit_ad_path+. @@ -499,6 +530,29 @@ If you like, you can combine shallow nesting with the +:has_one+ and +:has_many+ map.resources :publishers, :has_many => { :magazines => :photos }, :shallow => true ------------------------------------------------------- +=== Namespaced Resources + +It's possible to do some quite complex things by combining +:path_prefix+ and +:name_prefix+. For example, you can use the combination of these two options to move administrative resources to their own folder in your application: + +[source, ruby] +------------------------------------------------------- +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' +------------------------------------------------------- + +The good news is that if you find yourself using this level of complexity, you can stop. Rails supports _namespaced resources_ to make placing resources in their own folder a snap. Here's the namespaced version of those same three routes: + +[source, ruby] +------------------------------------------------------- +map.namespace(:admin) do |admin| + admin.resources :photos, + :has_many => { :tags, :ratings} +end +------------------------------------------------------- + +As you can see, the namespaced version is much more succinct than the one that spells everything out - but it still creates the same routes. For example, you'll get +admin_photos_url+ that expects to find an +Admin::PhotosController+ and that matches +admin/photos+, and +admin_photos_ratings+path+ that matches +/admin/photos/_photo_id_/ratings+, expecting to use +Admin::RatingsController+. Even though you're not specifying +path_prefix+ explicitly, the routing code will calculate the appropriate +path_prefix+ from the route nesting. + === Adding More RESTful Actions You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional member routes (those which apply to a single instance of the resource), additional new routes (those that apply to creating a new resource), or additional collection routes (those which apply to the collection of resources as a whole). @@ -514,7 +568,12 @@ map.resources :photos, :member => { :preview => :get } This will enable Rails to recognize URLs such as +/photos/1/preview+ using the GET HTTP verb, and route them to the preview action of the Photos controller. It will also create a +preview_photo+ route helper. -Within the hash of member routes, each route name specifies the HTTP verb that it will recognize. You can use +:get+, +:put+, +:post+, +:delete+, or +:any+ here. +Within the hash of member routes, each route name specifies the HTTP verb that it will recognize. You can use +:get+, +:put+, +:post+, +:delete+, or +:any+ here. You can also specify an array of methods, if you need more than one but you don't want to allow just anything: + +[source, ruby] +------------------------------------------------------- +map.resources :photos, :member => { :prepare => [:get, :post] } +------------------------------------------------------- ==== Adding Collection Routes @@ -527,6 +586,13 @@ map.resources :photos, :collection => { :search => :get } This will enable Rails to recognize URLs such as +/photos/search+ using the GET HTTP verb, and route them to the search action of the Photos controller. It will also create a +search_photos+ route helper. +Just as with member routes, you can specify an array of methods for a collection route: + +[source, ruby] +------------------------------------------------------- +map.resources :photos, :collection => { :search => [:get, :post] } +------------------------------------------------------- + ==== Adding New Routes To add a new route (one that creates a new resource), use the +:new+ option: @@ -574,7 +640,7 @@ You can set up as many wildcard symbols within a regular route as you like. Anyt [source, ruby] ------------------------------------------------------- -map.connect ':controller/:action/:id/:userid:' +map.connect ':controller/:action/:id/:user_id' ------------------------------------------------------- An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be set to 2. @@ -585,7 +651,7 @@ You can specify static text when creating a route. In this case, the static text [source, ruby] ------------------------------------------------------- -map.connect ':controller/:action/:id/with_user/:userid:' +map.connect ':controller/:action/:id/with_user/:user_id' ------------------------------------------------------- This route would respond to URLs such as +/photos/show/1/with_user/2+. @@ -612,6 +678,15 @@ map.connect 'photo/:id', :controller => 'photos', :action => 'show' With this route, an incoming URL of +/photos/12+ would be dispatched to the +show+ action within the +Photos+ controller. +You an also define other defaults in a route by supplying a hash for the +:defaults+ option. This even applies to parameters that are not explicitly defined elsewhere in the route. For example: + +[source, ruby] +------------------------------------------------------- +map.connect 'photo/:id', :controller => 'photos', :action => 'show', :defaults => { :format => 'jpg' } +------------------------------------------------------- + +With this route, an incoming URL of +photos/12+ would be dispatched to the +show+ action within the +Photos+ controller, and +params[:format]+ will be set to +jpg+. + === Named Routes Regular routes need not use the +connect+ method. You can use any other name here to create a _named route_. For example, @@ -655,7 +730,7 @@ As with conditions in RESTful routes, you can specify +:get+, +:post+, +:put+, + === Route Globbing -Route globbing is a way to specify that a particular parameter (which must be the last parameter in the route) should engulf all the remaining parts of a route. For example +Route globbing is a way to specify that a particular parameter (which must be the last parameter in the route) should be matched to all the remaining parts of a route. For example [source, ruby] ------------------------------------------------------- @@ -690,7 +765,7 @@ For instance, consider the second of the default routes in the boilerplate +rout map.connect ':controller/:action/:id.:format' ------------------------------------------------------- -This route matches requests such as +/photo/new/1.xml+ or +/photo/show/2.rss+. Within the appropriate action code, you can issue different responses depending on the requested format: +This route matches requests such as +/photo/edit/1.xml+ or +/photo/show/2.rss+. Within the appropriate action code, you can issue different responses depending on the requested format: [source, ruby] ------------------------------------------------------- @@ -750,7 +825,7 @@ map.index :controller => "pages", :action => "main" map.root :index ------------------------------------------------------- -Because of the top-down processing of the file, the named route must be specified _before_ the call to +map.route+. +Because of the top-down processing of the file, the named route must be specified _before_ the call to +map.root+. === Connecting the Empty String @@ -835,4 +910,12 @@ The +assert_routing+ assertion checks the route both ways: it tests that the pat [source, ruby] ------------------------------------------------------- assert_routing { :path => "photos", :method => :post }, { :controller => "photos", :action => "create" } --------------------------------------------------------
\ No newline at end of file +------------------------------------------------------- + +== Changelog == + +http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3[Lighthouse ticket] + +* October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes , by link:../authors.html#mgunderloy[Mike Gunderloy] +* September 23, 2008: Added section on namespaced controllers and routing, by link:../authors.html#mgunderloy[Mike Gunderloy] +* September 10, 2008: initial version by link:../authors.html#mgunderloy[Mike Gunderloy] |