mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #40593 from jonathanhefner/guide-routing-link-api
Link to API docs in Routing guide [ci-skip]
This commit is contained in:
commit
eb7cf21a96
1 changed files with 71 additions and 29 deletions
|
@ -83,7 +83,9 @@ NOTE: The `Rails.application.routes.draw do ... end` block that wraps your route
|
|||
Resource Routing: the Rails Default
|
||||
-----------------------------------
|
||||
|
||||
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.
|
||||
Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. A single call to [`resources`][] can declare all of the necessary routes for your `index`, `show`, `new`, `edit`, `create`, `update` and `destroy` actions.
|
||||
|
||||
[`resources`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-resources
|
||||
|
||||
### Resources on the Web
|
||||
|
||||
|
@ -200,7 +202,7 @@ As with plural resources, the same helpers ending in `_url` will also include th
|
|||
|
||||
### Controller Namespaces and Routing
|
||||
|
||||
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:
|
||||
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 the `app/controllers/admin` directory. You can route to such a group by using a [`namespace`][] block:
|
||||
|
||||
```ruby
|
||||
namespace :admin do
|
||||
|
@ -220,7 +222,7 @@ This will create a number of routes for each of the `articles` and `comments` co
|
|||
| PATCH/PUT | /admin/articles/:id | admin/articles#update | admin_article_path(:id) |
|
||||
| DELETE | /admin/articles/:id | admin/articles#destroy | admin_article_path(:id) |
|
||||
|
||||
If you want to route `/articles` (without the prefix `/admin`) to `Admin::ArticlesController`, you could use:
|
||||
If instead you want to route `/articles` (without the prefix `/admin`) to `Admin::ArticlesController`, you can specify the module with a [`scope`][] block:
|
||||
|
||||
```ruby
|
||||
scope module: 'admin' do
|
||||
|
@ -228,13 +230,13 @@ scope module: 'admin' do
|
|||
end
|
||||
```
|
||||
|
||||
or, for a single case:
|
||||
This can also be done for a single route:
|
||||
|
||||
```ruby
|
||||
resources :articles, module: 'admin'
|
||||
```
|
||||
|
||||
If you want to route `/admin/articles` to `ArticlesController` (without the `Admin::` module prefix), you could use:
|
||||
If instead you want to route `/admin/articles` to `ArticlesController` (without the `Admin::` module prefix), you can specify the path with a `scope` block:
|
||||
|
||||
```ruby
|
||||
scope '/admin' do
|
||||
|
@ -242,7 +244,7 @@ scope '/admin' do
|
|||
end
|
||||
```
|
||||
|
||||
or, for a single case:
|
||||
This can also be done for a single route:
|
||||
|
||||
```ruby
|
||||
resources :articles, path: '/admin/articles'
|
||||
|
@ -262,6 +264,9 @@ In each of these cases, the named routes remain the same as if you did not use `
|
|||
|
||||
TIP: _If you need to use a different controller namespace inside a `namespace` block you can specify an absolute controller path, e.g: `get '/foo', to: '/foo#index'`._
|
||||
|
||||
[`namespace`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-namespace
|
||||
[`scope`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-scope
|
||||
|
||||
### Nested Resources
|
||||
|
||||
It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
|
||||
|
@ -407,7 +412,7 @@ The comments resource here will have the following routes generated for it:
|
|||
|
||||
### Routing Concerns
|
||||
|
||||
Routing concerns allow you to declare common routes that can be reused inside other resources and routes. To define a concern:
|
||||
Routing concerns allow you to declare common routes that can be reused inside other resources and routes. To define a concern, use a [`concern`][] block:
|
||||
|
||||
```ruby
|
||||
concern :commentable do
|
||||
|
@ -440,7 +445,7 @@ resources :articles do
|
|||
end
|
||||
```
|
||||
|
||||
Also you can use them in any place that you want inside the routes, for example in a `scope` or `namespace` call:
|
||||
You can also use them anywhere by calling [`concerns`][]. For example, in a `scope` or `namespace` block:
|
||||
|
||||
```ruby
|
||||
namespace :articles do
|
||||
|
@ -448,6 +453,9 @@ namespace :articles do
|
|||
end
|
||||
```
|
||||
|
||||
[`concern`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Concerns.html#method-i-concern
|
||||
[`concerns`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Concerns.html#method-i-concerns
|
||||
|
||||
### Creating Paths and URLs from Objects
|
||||
|
||||
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:
|
||||
|
@ -496,7 +504,7 @@ You are not limited to the seven routes that RESTful routing creates by default.
|
|||
|
||||
#### Adding Member Routes
|
||||
|
||||
To add a member route, just add a `member` block into the resource block:
|
||||
To add a member route, just add a [`member`][] block into the resource block:
|
||||
|
||||
```ruby
|
||||
resources :photos do
|
||||
|
@ -509,7 +517,7 @@ end
|
|||
This will recognize `/photos/1/preview` with GET, and route to the `preview` action of `PhotosController`, with the resource id value passed in `params[:id]`. It will also create the `preview_photo_url` and `preview_photo_path` helpers.
|
||||
|
||||
Within the block of member routes, each route name specifies the HTTP verb that
|
||||
will be recognized. You can use `get`, `patch`, `put`, `post`, or `delete` here
|
||||
will be recognized. You can use [`get`][], [`patch`][], [`put`][], [`post`][], or [`delete`][] here
|
||||
. If you don't have multiple `member` routes, you can also pass `:on` to a
|
||||
route, eliminating the block:
|
||||
|
||||
|
@ -521,9 +529,17 @@ end
|
|||
|
||||
You can leave out the `:on` option, this will create the same member route except that the resource id value will be available in `params[:photo_id]` instead of `params[:id]`. Route helpers will also be renamed from `preview_photo_url` and `preview_photo_path` to `photo_preview_url` and `photo_preview_path`.
|
||||
|
||||
[`delete`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html#method-i-delete
|
||||
[`get`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html#method-i-get
|
||||
[`member`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-member
|
||||
[`patch`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html#method-i-patch
|
||||
[`post`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html#method-i-post
|
||||
[`put`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html#method-i-put
|
||||
[`put`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html#method-i-put
|
||||
|
||||
#### Adding Collection Routes
|
||||
|
||||
To add a route to the collection:
|
||||
To add a route to the collection, use a [`collection`][] block:
|
||||
|
||||
```ruby
|
||||
resources :photos do
|
||||
|
@ -545,6 +561,8 @@ end
|
|||
|
||||
NOTE: If you're defining additional resource routes with a symbol as the first positional argument, be mindful that it is not equivalent to using a string. Symbols infer controller actions while strings infer paths.
|
||||
|
||||
[`collection`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-collection
|
||||
|
||||
#### Adding Routes for Additional New Actions
|
||||
|
||||
To add an alternate new action using the `:on` shortcut:
|
||||
|
@ -620,7 +638,7 @@ get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' }
|
|||
|
||||
Rails would match `photos/12` to the `show` action of `PhotosController`, and set `params[:format]` to `"jpg"`.
|
||||
|
||||
You can also use `defaults` in a block format to define the defaults for multiple items:
|
||||
You can also use a [`defaults`][] block to define the defaults for multiple items:
|
||||
|
||||
```ruby
|
||||
defaults format: :json do
|
||||
|
@ -630,6 +648,8 @@ end
|
|||
|
||||
NOTE: You cannot override defaults via query parameters - this is for security reasons. The only defaults that can be overridden are dynamic segments via substitution in the URL path.
|
||||
|
||||
[`defaults`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-defaults
|
||||
|
||||
### Naming Routes
|
||||
|
||||
You can specify a name for any route using the `:as` option:
|
||||
|
@ -651,7 +671,7 @@ This will define a `user_path` method that will be available in controllers, hel
|
|||
|
||||
### HTTP Verb Constraints
|
||||
|
||||
In general, you should use the `get`, `post`, `put`, `patch` and `delete` methods to constrain a route to a particular verb. You can use the `match` method with the `:via` option to match multiple verbs at once:
|
||||
In general, you should use the [`get`][], [`post`][], [`put`][], [`patch`][], and [`delete`][] methods to constrain a route to a particular verb. You can use the [`match`][] method with the `:via` option to match multiple verbs at once:
|
||||
|
||||
```ruby
|
||||
match 'photos', to: 'photos#show', via: [:get, :post]
|
||||
|
@ -667,6 +687,8 @@ NOTE: Routing both `GET` and `POST` requests to a single action has security imp
|
|||
|
||||
NOTE: `GET` in Rails won't check for CSRF token. You should never write to the database from `GET` requests, for more information see the [security guide](security.html#csrf-countermeasures) on CSRF countermeasures.
|
||||
|
||||
[`match`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html#method-i-match
|
||||
|
||||
### Segment Constraints
|
||||
|
||||
You can use the `:constraints` option to enforce a format for a dynamic segment:
|
||||
|
@ -706,7 +728,7 @@ You specify a request-based constraint the same way that you specify a segment c
|
|||
get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' }
|
||||
```
|
||||
|
||||
You can also specify constraints in a block form:
|
||||
You can also specify constraints by using a [`constraints`][] block:
|
||||
|
||||
```ruby
|
||||
namespace :admin do
|
||||
|
@ -720,6 +742,8 @@ NOTE: Request constraints work by calling a method on the [Request object](actio
|
|||
|
||||
NOTE: There is an exception for the `format` constraint: while it's a method on the Request object, it's also an implicit optional parameter on every path. Segment constraints take precedence and the `format` constraint is only applied as such when enforced through a hash. For example, `get 'foo', constraints: { format: 'json' }` will match `GET /foo` because the format is optional by default. However, you can [use a lambda](#advanced-constraints) like in `get 'foo', constraints: lambda { |req| req.format == :json }` and the route will only match explicit JSON requests.
|
||||
|
||||
[`constraints`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-constraints
|
||||
|
||||
### 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 restricted list to the `RestrictedListController`. You could do:
|
||||
|
@ -821,7 +845,7 @@ get '*pages', to: 'pages#show', format: true
|
|||
|
||||
### Redirection
|
||||
|
||||
You can redirect any path to another path using the `redirect` helper in your router:
|
||||
You can redirect any path to another path using the [`redirect`][] helper in your router:
|
||||
|
||||
```ruby
|
||||
get '/stories', to: redirect('/articles')
|
||||
|
@ -848,6 +872,8 @@ get '/stories/:name', to: redirect('/articles/%{name}', status: 302)
|
|||
|
||||
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.
|
||||
|
||||
[`redirect`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Redirection.html#method-i-redirect
|
||||
|
||||
### Routing to Rack Applications
|
||||
|
||||
Instead of a String like `'articles#index'`, which corresponds to the `index` action in the `ArticlesController`, you can specify any [Rack application](rails_on_rack.html) as the endpoint for a matcher:
|
||||
|
@ -869,15 +895,17 @@ match '/admin', to: AdminApp, via: :all
|
|||
```
|
||||
|
||||
If you would prefer to have your Rack application receive requests at the root
|
||||
path instead, use `mount`:
|
||||
path instead, use [`mount`][]:
|
||||
|
||||
```ruby
|
||||
mount AdminApp, at: '/admin'
|
||||
```
|
||||
|
||||
[`mount`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html#method-i-mount
|
||||
|
||||
### Using `root`
|
||||
|
||||
You can specify what Rails should route `'/'` to with the `root` method:
|
||||
You can specify what Rails should route `'/'` to with the [`root`][] method:
|
||||
|
||||
```ruby
|
||||
root to: 'pages#main'
|
||||
|
@ -898,6 +926,8 @@ end
|
|||
root to: "home#index"
|
||||
```
|
||||
|
||||
[`root`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-root
|
||||
|
||||
### Unicode Character Routes
|
||||
|
||||
You can specify unicode character routes directly. For example:
|
||||
|
@ -908,7 +938,7 @@ get 'こんにちは', to: 'welcome#index'
|
|||
|
||||
### Direct Routes
|
||||
|
||||
You can create custom URL helpers directly. For example:
|
||||
You can create custom URL helpers directly by calling [`direct`][]. For example:
|
||||
|
||||
```ruby
|
||||
direct :homepage do
|
||||
|
@ -931,9 +961,11 @@ direct :main do
|
|||
end
|
||||
```
|
||||
|
||||
[`direct`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/CustomUrls.html#method-i-direct
|
||||
|
||||
### Using `resolve`
|
||||
|
||||
The `resolve` method allows customizing polymorphic mapping of models. For example:
|
||||
The [`resolve`][] method allows customizing polymorphic mapping of models. For example:
|
||||
|
||||
``` ruby
|
||||
resource :basket
|
||||
|
@ -949,10 +981,12 @@ resolve("Basket") { [:basket] }
|
|||
|
||||
This will generate the singular URL `/basket` instead of the usual `/baskets/:id`.
|
||||
|
||||
[`resolve`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/CustomUrls.html#method-i-resolve
|
||||
|
||||
Customizing Resourceful Routes
|
||||
------------------------------
|
||||
|
||||
While the default routes and helpers generated by `resources :articles` 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.
|
||||
While the default routes and helpers generated by [`resources`][] 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.
|
||||
|
||||
### Specifying a Controller to Use
|
||||
|
||||
|
@ -1139,7 +1173,7 @@ Rails now creates routes to the `CategoriesController`.
|
|||
|
||||
### Overriding the Singular Form
|
||||
|
||||
If you want to define the singular form of a resource, you should add additional rules to the `Inflector`:
|
||||
If you want to define the singular form of a resource, you should add additional rules to the `Inflector` via [`inflections`][]:
|
||||
|
||||
```ruby
|
||||
ActiveSupport::Inflector.inflections do |inflect|
|
||||
|
@ -1147,6 +1181,8 @@ ActiveSupport::Inflector.inflections do |inflect|
|
|||
end
|
||||
```
|
||||
|
||||
[`inflections`]: https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-inflections
|
||||
|
||||
### Using `:as` in Nested Resources
|
||||
|
||||
The `:as` option overrides the automatically-generated name for the resource in nested route helpers. For example:
|
||||
|
@ -1201,7 +1237,7 @@ Breaking up *very* large route file into multiple small ones:
|
|||
If you work in a large application with thousands of routes,
|
||||
a single `config/routes.rb` file can become cumbersome and hard to read.
|
||||
|
||||
Rails offers a way to break a gigantic single `routes.rb` file into multiple small ones using the `draw` macro.
|
||||
Rails offers a way to break a gigantic single `routes.rb` file into multiple small ones using the [`draw`][] macro.
|
||||
|
||||
```ruby
|
||||
# config/routes.rb
|
||||
|
@ -1225,6 +1261,8 @@ The file needs to be located inside the `config/routes` directory or any sub-dir
|
|||
|
||||
You can use the normal routing DSL inside the `admin.rb` routing file, **however** you shouldn't surround it with the `Rails.application.routes.draw` block like you did in the main `config/routes.rb` file.
|
||||
|
||||
[`draw`]: https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-draw
|
||||
|
||||
### When to use and not use this feature
|
||||
|
||||
Drawing routes from external files can be very useful to organise a large set of routes into multiple organised ones. You could have a `admin.rb` route that contains all the routes for the admin area, another `api.rb` file to route API related resources etc...
|
||||
|
@ -1305,15 +1343,19 @@ TIP: You'll find that the output from `bin/rails routes` is much more readable i
|
|||
|
||||
### Testing Routes
|
||||
|
||||
Routes should be included in your testing strategy (just like the rest of your application). Rails offers three [built-in assertions](https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html) designed to make testing routes simpler:
|
||||
Routes should be included in your testing strategy (just like the rest of your application). Rails offers three built-in assertions designed to make testing routes simpler:
|
||||
|
||||
* `assert_generates`
|
||||
* `assert_recognizes`
|
||||
* `assert_routing`
|
||||
* [`assert_generates`][]
|
||||
* [`assert_recognizes`][]
|
||||
* [`assert_routing`][]
|
||||
|
||||
[`assert_generates`]: https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_generates
|
||||
[`assert_recognizes`]: https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_recognizes
|
||||
[`assert_routing`]: https://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_routing
|
||||
|
||||
#### The `assert_generates` Assertion
|
||||
|
||||
`assert_generates` asserts that a particular set of options generate a particular path and can be used with default routes or custom routes. For example:
|
||||
[`assert_generates`][] asserts that a particular set of options generate a particular path and can be used with default routes or custom routes. For example:
|
||||
|
||||
```ruby
|
||||
assert_generates '/photos/1', { controller: 'photos', action: 'show', id: '1' }
|
||||
|
@ -1322,7 +1364,7 @@ assert_generates '/about', controller: 'pages', action: 'about'
|
|||
|
||||
#### The `assert_recognizes` Assertion
|
||||
|
||||
`assert_recognizes` is the inverse of `assert_generates`. It asserts that a given path is recognized and routes it to a particular spot in your application. For example:
|
||||
[`assert_recognizes`][] is the inverse of `assert_generates`. It asserts that a given path is recognized and routes it to a particular spot in your application. For example:
|
||||
|
||||
```ruby
|
||||
assert_recognizes({ controller: 'photos', action: 'show', id: '1' }, '/photos/1')
|
||||
|
@ -1336,7 +1378,7 @@ assert_recognizes({ controller: 'photos', action: 'create' }, { path: 'photos',
|
|||
|
||||
#### 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`:
|
||||
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
|
||||
assert_routing({ path: 'photos', method: :post }, { controller: 'photos', action: 'create' })
|
||||
|
|
Loading…
Reference in a new issue