Routing

Ruby on Rails · Essentials · 12 min

Routes define your app's URL design and generate the path helpers used throughout views and controllers.

config/routes.rb maps HTTP verbs and paths to controller#action:

Rails.application.routes.draw do
  root "articles#index"
  get "/about", to: "pages#about", as: :about
  resources :articles
end

resources :articles creates the seven RESTful routes: index (GET /articles), new, create (POST /articles), show (GET /articles/:id), edit, update (PATCH/PUT /articles/:id) and destroy (DELETE). Limit them with only: [:index, :show] or except:. Use resource :profile (singular) for things a user has only one of.

Every named route generates path and URL helpers: articles_path gives /articles, article_path(@article) gives /articles/42, edit_article_path(@article), new_article_path, and _url versions with the host. Use them everywhere instead of literal strings.

Organising routes:

  • Nested resources express ownership: resources :articles do resources :comments, only: [:create, :destroy] end gives /articles/:article_id/comments. Keep nesting one level deep (use shallow: true for deeper hierarchies).
  • member { post :publish } adds /articles/:id/publish; collection { get :search } adds /articles/search.
  • namespace :admin do ... end prefixes paths, helpers and controllers (Admin::UsersController).
  • Dynamic segments and constraints: get "/u/:username", to: "users#show", constraints: { username: /[a-z0-9_]+/ }.

bin/rails routes lists everything, with -g to filter. Routes match top to bottom; the first match wins.

Example

# config/routes.rb
Rails.application.routes.draw do
  root "articles#index"

  resources :articles do
    member { post :publish }               # POST /articles/:id/publish
    collection { get :search }             # GET  /articles/search
    resources :comments, only: %i[create destroy]
  end

  resource :session                        # singular: /session
  get "/@:username", to: "profiles#show", as: :profile,
      constraints: { username: /[a-z0-9_]+/ }

  namespace :admin do
    resources :users, only: %i[index update]   # Admin::UsersController
  end

  get "up" => "rails/health#show", as: :rails_health_check
end

# Helpers: article_path(@article)              => "/articles/42"
#          article_comments_path(@article)      => "/articles/42/comments"
#          publish_article_path(@article)       => "/articles/42/publish"
#          profile_path(username: "ada")        => "/@ada"

Remember

  • resources :things generates the seven RESTful routes and helpers
  • Use path helpers like article_path(@article) instead of literal URLs
  • Nest one level for ownership; use member, collection and namespace to organise

Watch out for

  • Deeply nesting resources, producing unwieldy URLs and helpers; prefer shallow nesting.

Check yourself

  1. Which request does resources :articles map to ArticlesController#update?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: guides.rubyonrails.org/routing.html