# Routing
# Basic Routing
The most basic Rails routes accept a URI and Controller method, providing a very simple and expressive method of defining routes and behavior without complicated routing configuration files:
get '/photos', to: 'photos#index'
the request is dispatched to the photos controller's index action .
The Default Route Files
All Rails routes are defined in your route files, which are located in the config directory.
Available Route Methods
Rails supports four different routes methods in application
get 'uri', to: 'controller#method' post 'uri', to: 'controller#method' patch/put 'uri', to: 'controller#method' delete 'uri', to: 'controller#method'
1
2
3
4CSRF Protection
Remember, any HTML forms pointing to
POST
,PUT
,PATCH
, orDELETE
routes that are defined in theweb
routes file should include a CSRF token field. Otherwise, the request will be rejected.As a Rails developer, you basically get CSRF protection for free. It starts with this single line in application_controller.rb, which enables CSRF protection:
protect_from_forgery with: :exception
1Next, there's this single line in application.html.erb:
<%= csrf_meta_tags %>
1Redirect Routes
You can redirect any path to another path by using the
[redirect](https://api.rubyonrails.org/v7.0.4/classes/ActionDispatch/Routing/Redirection.html#method-i-redirect)
helper in your router:get '/stories', to: redirect('/articles')
1You can also reuse dynamic segments from the match in the path to redirect to:
get '/stories/:name', to: redirect('/articles/%{name}'
1You can also provide a block to
redirect
, which receives the symbolized path parameters and the request object:get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" } get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" }
1
2Please note that default redirection is a 301 "Moved Permanently" redirect. Keep in mind that some web browsers or proxy servers will cache this type of redirect, making the old page inaccessible. You can use the
:status
option to change the response status:get '/stories/:name', to: redirect('/articles/%{name}', status: 302)
1The Route List
The routes Artisan command can easily provide an overview of all of the routes that are defined by your application:
bin/rails routes
1You can also use the
--expanded
option to turn on the expanded table formatting mode.You can search through your routes with the grep option: -g. This outputs any routes that partially match the URL helper method name, the HTTP verb, or the URL path.
bin/rails routes -g new_comment bin/rails routes -g POST bin/rails routes -g admin
1
2
3If you only want to see the routes that map to a specific controller, there's the -c option.
bin/rails routes -c users bin/rails routes -c admin/users bin/rails routes -c Comments bin/rails routes -c Articles::CommentsController
1
2
3
4Route Globbling and Wildcard Segments
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example:
get 'photos/*other', to: 'photos#unknown'
1This route would match
photos/12
or/photos/long/path/to/12
, settingparams[:other]
to"12"
or"long/path/to/12"
. The segments prefixed with a star are called "wildcard segments".Using root
You can specify what Rails should route
'/'
to with the[root](https://api.rubyonrails.org/v7.0.4/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-root)
method:root to: 'pages#main' root 'pages#main' # shortcut for the above
1
2You should put the
root
route at the top of the file, because it is the most popular route and should be matched first.
# Routes Parameters
Required Parameters
Sometimes you will need to capture segments of the URI within your route. For example, you may need to capture a user's ID from the URL. You may do so by defining route parameters:
get 'users/:id', to: 'users#display'
1If an incoming request of
/photos/1
is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke thedisplay
action of thePhotosController
, and to make the final parameter"1"
available asparams[:id]
. This route will also route the incoming request of/photos
toPhotosController#display
, since:
is an optional parameter, denoted by parentheses.You can set up as many dynamic segments within a regular route as you like. Any segment will be available to the action as part of
params
.get 'photos/:id/:user_id', to: 'photos#show'
1The Query String
The
params
will also include any parameters from the query string. For example, with this route:get 'photos/:id', to: 'photos#show'
1An incoming path of
/photos/1?user_id=2
will be dispatched to theshow
action of thePhotos
controller.params
will be{ controller: 'photos', action: 'show', id: '1', user_id: '2' }
.Defining Defaults
You can define 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:get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' }
1
2You can also use a
[defaults](https://api.rubyonrails.org/v7.0.4/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-defaults)
block to define the defaults for multiple items:defaults format: :json do resources :photos end
1
2
3Regular Expression Constraints
You can use the
:constraints
option to enforce a format for a dynamic segment:get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ }
1Named Routes
You can specify a name for any route using the
:as
option:get 'exit', to: 'sessions#destroy', as: :logout
1This will create
logout_path
andlogout_url
as named route helpers in your application. Callinglogout_path
will return/exit
# Resource Routing
Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. A single call to [resources](https://api.rubyonrails.org/v7.0.4/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-resources)
can declare all of the necessary routes for your index
, show
, new
, edit
, create
, update
, and destroy
actions.
resources :photos
creates seven different routes in your application, all mapping to the Photos
controller:
| --- | --- | --- | --- |
Path and URL Helper
Creating a resourceful route will also expose a number of helpers to the controllers in your application. In the case of
resources :photos
:photos_path
returns/photos
new_photo_path
returns/photos/new
edit_photo_path(:id)
returns/photos/:id/edit
(for instance,edit_photo_path(10)
returns/photos/10/edit
)photo_path(:id)
returns/photos/:id
(for instance,photo_path(10)
returns/photos/10
)
Each of these helpers has a corresponding
_url
helper (such asphotos_url
) which returns the same path prefixed with the current host, port, and path prefix.Defining Multiple Resource at same time
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
:resources :photos, :books, :videos
1This works exactly the same as:
resources :photos resources :books resources :videos
1
2
3
# Route Groups
Controllers
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, and place these controllers under theapp/controllers/admin
directory. You can route to such a group by using a[namespace](https://api.rubyonrails.org/v7.0.4/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-namespace)
block:namespace :admin do resources :articles, :comments end
1
2
3This will create a number of routes for each of the
articles
andcomments
controller. ForAdmin::ArticlesController
, Rails will create:| --- | --- | --- | --- |
If instead you want to route
/articles
(without the prefix/admin
) toAdmin::ArticlesController
, you can specify the module with a[scope](https://api.rubyonrails.org/v7.0.4/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-scope)
block:Nested Resources
It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
class Magazine < ApplicationRecord has_many :ads end class Ad < ApplicationRecord belongs_to :magazine end
1
2
3
4
5
6
7Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration:
resources :magazines do resources :ads end
1
2
3In addition to the routes for magazines, this declaration will also route ads to an
AdsController
. The ad URLs require a magazine:| --- | --- | --- | --- |
This will also create routing helpers such as
magazine_ads_url
andedit_magazine_ad_path
. These helpers take an instance of Magazine as the first parameter (magazine_ads_url(@magazine)
).Routing Concerns