Ruby on Rails


Routing All Versions

1.0
1.1
1.2
2.0
2.3
3.0
3.1
3.2
4.0
4.1
4.2
5.0

This draft deletes the entire topic.

Introduction

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.
expand all collapse all

Examples

  • 70

    Routes are defined in config/routes.rb. They are often defined as a group of related routes, using the resources or resource methods.

    resources :users creates the following seven routes, all mapping to actions of UsersController:

    get       '/users',          to: 'users#index'
    post      '/users',          to: 'users#create'
    get       '/users/new',      to: 'users#new'
    get       '/users/:id/edit', to: 'users#edit'
    get       '/users/:id',      to: 'users#show'
    patch/put '/users/:id',      to: 'users#update'
    delete    '/users/:id',      to: 'users#destroy'
    

    Action names are shown after the # in the to parameter above. Methods with those same names must be defined in app/controllers/users_controller.rb as follows:

    class UsersController < ApplicationController
      def index
      end
    
      def create
      end
    
      # continue with all the other methods…
    end
    

    You can limit the actions that gets generated with only or except:

    resources :users, only:   [:show]
    resources :users, except: [:show, :index]
    

    To view all the routes of your application at any given time by running

    5.0
    $ rake routes
    
    5.0
    $ rake routes
    # OR
    $ rails routes
    
    users     GET    /users(.:format)          users#index
              POST   /users(.:format)          users#create
    new_user  GET    /users/new(.:format)      users#new
    edit_user GET    /users/:id/edit(.:format) users#edit
    user      GET    /users/:id(.:format)      users#show
              PATCH  /users/:id(.:format)      users#update
              PUT    /users/:id(.:format)      users#update
              DELETE /users/:id(.:format)      users#destroy
    

    To see only the routes that map to a particular controller:

    5.0
    $ rake routes -c static_pages
    static_pages_home    GET    /static_pages/home(.:format)    static_pages#home
    static_pages_help    GET    /static_pages/help(.:format)    static_pages#help
    
    5.0
    $ rake routes -c static_pages
    static_pages_home    GET    /static_pages/home(.:format)    static_pages#home
    static_pages_help    GET    /static_pages/help(.:format)    static_pages#help
    
    # OR
    
    $ rails routes -c static_pages
    static_pages_home    GET    /static_pages/home(.:format)    static_pages#home
    static_pages_help    GET    /static_pages/help(.:format)    static_pages#help
    

    You can search through routes using the -g option. This shows any route that partially matches the helper method name, the URL path or the HTTP verb:

    5.0
    $ rake routes -g new_user     # Matches helper method
    $ rake routes -g POST         # Matches HTTP Verb POST 
    
    5.0
    $ rake routes -g new_user     # Matches helper method
    $ rake routes -g POST         # Matches HTTP Verb POST 
    # OR
    $ rails routes -g new_user    # Matches helper method
    $ rails routes -g POST        # Matches HTTP Verb POST 
    

    Additionally, when running rails server in development mode, you can access a web page that shows all your routes with a search filter, matched in priority from top to bottom, at <hostname>/rails/info/routes. It will look like this:

    HelperHTTP VerbPathController#Action
    Path / Url[ Path Match ]
    users_pathGET/users(.:format)users#index
    POST/users(.:format)users#create
    new_user_pathGET/users/new(.:format)users#new
    edit_user_pathGET/users/:id/edit(.:format)users#edit
    user_pathGET/users/:id(.:format)users#show
    PATCH/users/:id(.:format)users#update
    PUT/users/:id(.:format)users#update
    DELETE/users/:id(.:format)users#destroy

    Routes can be declared available for only members (not collections) using the method resource instead of resources in routes.rb. With resource, an index route is not created by default, but only when explicitly asking for one like this:

    resource :orders, only: [:index, :create, :show]
    
  • 26

    You can filter what routes are available using constraints.

    There are several ways to use constraints including:

    For example, a requested based constraint to only allow a specific IP address to access a route:

    constraints(ip: /127\.0\.0\.1$/) do
      get 'route', to: "controller#action"
    end
    

    See other similar examples ActionDispatch::Routing::Mapper::Scoping.

    If you want to do something more complex you can use more advanced constraints and create a class to wrap the logic:

    # lib/api_version_constraint.rb
    class ApiVersionConstraint
      def initialize(version:, default:)
        @version = version
        @default = default
      end
    
      def version_header
        "application/vnd.my-app.v#{@version}"
      end
    
      def matches?(request)
        @default || request.headers["Accept"].include?(version_header)
      end
    end
    
    # config/routes.rb
    require "api_version_constraint"
    
    Rails.application.routes.draw do
      namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
        resources :users # Will route to app/controllers/v1/users_controller.rb
      end
    
      namespace :v2, constraints: ApiVersionConstraint.new(version: 2) do
        resources :users # Will route to app/controllers/v2/users_controller.rb
      end
    end
    

    One form, several submit buttons

    You can also use the value of the submit tags of a form as a constraint to route to a different action. If you have a form with multiple submit buttons (eg "preview" and "submit"), you could capture this constraint directly in your routes.rb, instead of writing javascript to change the form destination URL. For example with the commit_param_routing gem you can take advantage of rails submit_tag

    Rails submit_tag first parameter lets you change the value of your form commit parameter

    # app/views/orders/mass_order.html.erb
    <%= form_for(@orders, url: mass_create_order_path do |f| %>
        <!-- Big form here -->
      <%= submit_tag "Preview" %>
      <%= submit_tag "Submit" %>
      # => <input name="commit" type="submit" value="Preview" />
      # => <input name="commit" type="submit" value="Submit" />
      ...
    <% end %>
    
    # config/routes.rb
    resources :orders do
      # Both routes below describe the same POST URL, but route to different actions 
      post 'mass_order', on: :collection, as: 'mass_order',
        constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses "submit"
      post 'mass_order', on: :collection,
        constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user presses "preview"
      # Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form url
      # CommitParamRouting is just a class like ApiVersionContraint
    end
    
  • Improvements requested:

    • This example does not sufficiently illustrate the point and needs to be edited to provide more details. –  Ancinek Jan 5 at 19:48
      It would be nice to see the generated routes for shallow_scoping;
    19

    Rails provides several ways to organize your routes.

    Scope by URL:

    scope 'admin' do
      get 'dashboard', to: 'administration#dashboard'
      resources 'employees'
    end
    

    This generates the following routes

    get       '/admin/dashboard',          to: 'administration#dashboard'
    post      '/admin/employees',          to: 'employees#create'
    get       '/admin/employees/new',      to: 'employees#new'
    get       '/admin/employees/:id/edit', to: 'employees#edit'
    get       '/admin/employees/:id',      to: 'employees#show'
    patch/put '/admin/employees/:id',      to: 'employees#update'
    delete    '/admin/employees/:id',      to: 'employees#destroy'
    

    It may make more sense, on the server side, to keep some views in a different subfolder, to separate admin views from user views.

    Scope by module

    scope module: :admin do
      get 'dashboard', to: 'administration#dashboard'
    end
    

    module looks for the controller files under the subfolder of the given name

    get       '/dashboard',          to: 'admin/administration#dashboard'
    

    You can rename the path helpers prefix by adding an as parameter

    scope 'admin', as: :administration do
      get 'dashboard'
    end
    
    # => administration_dashboard_path
    

    Rails provides a convenient way to do all the above, using the namespace method. The following declarations are equivalent

    namespace :admin do
    end
    
    scope 'admin', module: :admin, as: :admin
    

    Scope by controller

    scope controller: :management do
      get 'dashboard'
      get 'performance'
    end
    

    This generate these routes

    get       '/dashboard',          to: 'management#dashboard'
    get       '/performance',        to: 'management#performance'
    

    Shallow Nesting

    Resources shouldn't be nested more than one level deep. One way to avoid this is by creating shallow routes. There are two options for scope to custom shallow routes

    • :shallow_path: Prefixes member paths with a specified parameter

      scope shallow_path: "sekret" do
        resources :articles do
          resources :comments, shallow: true
        end
      end
      
    • :shallow_prefix: Add specified parameters to named helpers

      scope shallow_prefix: "sekret" do
        resources :articles do
          resources :comments, shallow: true
        end
      end
      
Please consider making a request to improve this example.

Syntax

Syntax

Parameters

Parameters

Remarks

"Routing" in general is how URL's are "handled" by your app. In Rails case it's typically which controller and which action of that controller will handle a particular incoming URL. In Rails apps, routes are usually placed in the config/routes.rb file.

Still have a question about Routing? Ask Question

Topic Outline