Skip
Arish's avatar

17. Routing in Rails


Routing in Rails

The router is the traffic controller of your Rails app. It receives incoming requests and dispatches them to the appropriate controller action.

The Routes File

All routes are defined in config/routes.rb:

ruby
1Rails.application.routes.draw do
2  # Your routes go here
3end

Basic Routes

Simple Routes

ruby
1# GET /welcome → WelcomeController#index
2get '/welcome', to: 'welcome#index'
3
4# POST /articles → ArticlesController#create
5post '/articles', to: 'articles#create'
6
7# Route with dynamic segment
8get '/articles/:id', to: 'articles#show'
9# /articles/1 → params[:id] = "1"
10# /articles/42 → params[:id] = "42"

Root Route

The homepage of your application:

ruby
1# GET / → PagesController#home
2root 'pages#home'
3
4# Or using a specific controller action
5root to: 'articles#index'

RESTful Routes with Resources

The resources method generates all CRUD routes:

ruby
1resources :articles

This creates these routes:

HTTP VerbPathController#ActionUsed For
GET/articlesarticles#indexList all articles
GET/articles/newarticles#newForm for new article
POST/articlesarticles#createCreate an article
GET/articles/:idarticles#showShow an article
GET/articles/:id/editarticles#editForm to edit article
PATCH/PUT/articles/:idarticles#updateUpdate an article
DELETE/articles/:idarticles#destroyDelete an article

Limiting Routes

ruby
1# Only specific actions
2resources :articles, only: [:index, :show]
3
4# All except specific actions
5resources :articles, except: [:destroy]

Singular Resource

For resources where there's only one (like current user profile):

ruby
1resource :profile
2# GET /profile → profiles#show
3# GET /profile/edit → profiles#edit
4# PATCH /profile → profiles#update

Nested Resources

For resources that belong to other resources:

ruby
1resources :articles do
2  resources :comments
3end

This creates routes like:

  • GET /articles/:article_id/comments → comments#index
  • POST /articles/:article_id/comments → comments#create
  • GET /articles/:article_id/comments/:id → comments#show
ruby
1# In CommentsController
2class CommentsController < ApplicationController
3  def create
4    @article = Article.find(params[:article_id])
5    @comment = @article.comments.build(comment_params)
6    @comment.save
7  end
8end

Shallow Nesting

Avoid deeply nested routes:

ruby
1resources :articles do
2  resources :comments, shallow: true
3end
4
5# Creates:
6# /articles/:article_id/comments (index, new, create)
7# /comments/:id (show, edit, update, destroy)

Custom Routes

Member Routes

Actions on a specific resource:

ruby
1resources :articles do
2  member do
3    post :publish
4    delete :archive
5  end
6end
7
8# POST /articles/:id/publish → articles#publish
9# DELETE /articles/:id/archive → articles#archive

Shorthand for single action:

ruby
1resources :articles do
2  post :publish, on: :member
3end

Collection Routes

Actions on the entire collection:

ruby
1resources :articles do
2  collection do
3    get :search
4    get :drafts
5  end
6end
7
8# GET /articles/search → articles#search
9# GET /articles/drafts → articles#drafts

Named Routes and Helpers

Rails generates URL helper methods for each route:

ruby
1resources :articles

This creates these helpers:

ruby
1articles_path          # /articles
2articles_url           # http://example.com/articles
3new_article_path       # /articles/new
4article_path(@article) # /articles/1
5edit_article_path(@article) # /articles/1/edit

Use them in views and controllers:

erb
1<!-- In views -->
2<%= link_to 'All Articles', articles_path %>
3<%= link_to article.title, article_path(article) %>
4<%= link_to 'Edit', edit_article_path(article) %>
5
6<!-- Shorthand with resources -->
7<%= link_to 'View', article %>
8<%= link_to 'Edit', [:edit, article] %>

Custom Path Names

ruby
1resources :articles, path: 'posts'
2# /posts, /posts/:id instead of /articles, /articles/:id
3
4resources :articles, path_names: { new: 'create', edit: 'modify' }
5# /articles/create, /articles/:id/modify

Named Routes with 'as'

ruby
1get '/login', to: 'sessions#new', as: :login
2# login_path → /login
3
4get '/dashboard', to: 'admin#dashboard', as: :admin_dashboard
5# admin_dashboard_path → /dashboard

Namespaces and Scopes

Namespace

Groups controllers under a module and changes the URL:

ruby
1namespace :admin do
2  resources :articles
3end
4
5# URL: /admin/articles
6# Controller: Admin::ArticlesController
7# Views: app/views/admin/articles/
ruby
1# app/controllers/admin/articles_controller.rb
2module Admin
3  class ArticlesController < ApplicationController
4    def index
5      @articles = Article.all
6    end
7  end
8end

Scope

Changes the URL but not the controller module:

ruby
1scope '/admin' do
2  resources :articles
3end
4
5# URL: /admin/articles
6# Controller: ArticlesController (no module)

Module Only

Changes the controller module but not the URL:

ruby
1scope module: 'admin' do
2  resources :articles
3end
4
5# URL: /articles
6# Controller: Admin::ArticlesController

Route Constraints

Format Constraints

ruby
1# Only respond to JSON
2resources :articles, constraints: { format: 'json' }
3
4# Multiple formats
5get '/feed', to: 'articles#feed', constraints: { format: /(rss|atom)/ }

Custom Constraints

ruby
1# Only numeric IDs
2resources :articles, constraints: { id: /\d+/ }
3
4# Subdomain constraint
5constraints subdomain: 'api' do
6  resources :articles
7end
8
9# Custom constraint class
10class AuthenticatedConstraint
11  def matches?(request)
12    request.session[:user_id].present?
13  end
14end
15
16constraints AuthenticatedConstraint.new do
17  resources :dashboard
18end

Redirects

ruby
1# Simple redirect
2get '/old-path', to: redirect('/new-path')
3
4# Dynamic redirect
5get '/articles/:id', to: redirect('/posts/%{id}')
6
7# Redirect with status code
8get '/old', to: redirect('/new', status: 301)

Viewing Routes

bash
1# See all routes
2rails routes
3
4# Filter routes
5rails routes -c articles    # Only ArticlesController
6rails routes -g search      # Routes matching "search"

Route Organization

For large applications, organize routes:

ruby
1# config/routes.rb
2Rails.application.routes.draw do
3  root 'home#index'
4  
5  # Public routes
6  resources :articles, only: [:index, :show]
7  
8  # Authenticated routes
9  authenticate :user do
10    resources :articles, except: [:index, :show]
11  end
12  
13  # Admin namespace
14  namespace :admin do
15    resources :users
16    resources :articles
17  end
18  
19  # API namespace
20  namespace :api do
21    namespace :v1 do
22      resources :articles, only: [:index, :show]
23    end
24  end
25end

Routes are the entry point to your application - design them thoughtfully!