Skip to content

Ruby on Rails Routing Deep — Advanced Routing Techniques

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Ruby on Rails Routing Deep. We cover key concepts, practical examples, and best practices to help you master this topic.

Rails routing maps URLs to controller actions with resourceful routes, nested resources, concerns, constraints, scoping, and route introspection for debugging.

What You'll Learn

By the end of this tutorial, you'll define resourceful routes with member and collection routes, use constraints for subdomain and format restrictions, share route concerns, and mount engines.

Why Routing Matters

Routes are the public API of your application. Well-designed routes follow REST conventions, support versioning, and remain maintainable as the application grows.

Real-World Use

A multi-tenant SaaS uses subdomain constraints to route to tenant-specific controllers and namespace routing for API Versioning (api/v1/products).

Routing Path

flowchart LR
  A[Rails Routing] --> B[Resources]
  A --> C[Constraints]
  A --> D[Concerns]
  A --> E[Engines]
  A --> F{You Are Here}
  style F fill:#f90,color:#fff

Resourceful Routes Deep

Advanced resourceful routing options.

# config/routes.rb
Rails.application.routes.draw do
  resources :products do
    # Collection routes (no ID)
    collection do
      get :search
      post :bulk_import
    end
    # Member routes (with ID)
    member do
      patch :publish
      get :history
    end
    # Shorthand syntax
    get :search, on: :collection
    patch :publish, on: :member
  end
end

Constraints

Add constraints to routes.

Rails.application.routes.draw do
  # Subdomain constraint
  constraints(subdomain: "api") do
    namespace :api do
      resources :products
    end
  end
  # Format constraint
  constraints(format: :json) do
    resources :api_keys, only: [:create]
  end
  # Custom constraint class
  class AdminConstraint
    def matches?(request)
      request.session[:user_id] && User.find(request.session[:user_id]).admin?
    end
  end
  constraints(AdminConstraint.new) do
    namespace :admin do
      resources :dashboard, only: [:index]
    end
  end
end

Route Concerns

Share common route configurations.

Rails.application.routes.draw do
  concern :commentable do
    resources :comments
  end
  concern :likeable do
    resources :likes, only: [:create, :destroy]
  end
  resources :posts, concerns: [:commentable, :likeable]
  resources :photos, concerns: [:commentable, :likeable]
  # Equivalent to:
  # resources :posts do
  #   resources :comments
  #   resources :likes, only: [:create, :destroy]
  # end
end

Route Scoping

Scope routes with modules, paths, and names.

Rails.application.routes.draw do
  # Namespace: /admin/products -> Admin::ProductsController
  namespace :admin do
    resources :products
  end
  # Scope module: /products -> Admin::ProductsController
  scope module: :admin do
    resources :products
  end
  # Scope path: /admin/products -> ProductsController
  scope path: :admin do
    resources :products
  end
  # Scope with defaults
  scope "(:locale)", locale: /en|es|fr/ do
    resources :products
  end
end

Common Mistakes

1. Deep Nesting Routes

resources :posts do resources :comments do resources :likes end end creates long URLs. Limit nesting to one level.

2. Exposing Too Many Routes

resources :products generates 7 routes. Use only: to expose only needed actions.

3. Not Using Concerns for Repeated Patterns

Duplicating the same nested routes across resources violates DRY. Use concerns.

4. Ignoring Route Order

Rails matches routes top-to-bottom. Place catch-all routes at the bottom.

5. Missing Constraints for SEO

Unconstrained routes match any format. Use constraints for format-specific behavior.

Practice Questions

1. What is the difference between member and collection routes?

Member routes require an ID. Collection routes do not.

2. How do you share routes across multiple resources?

Define a concern with the shared routes and include it in each resource.

3. What is route scoping?

Grouping routes with common controller module, path prefix, or name prefix.

4. How do you restrict routes to JSON format?

Use constraints(format: :json) inside the route block.

5. Challenge: Create a nested route with concerns and constraints.

concern :searchable do
  collection { get :search }
end
resources :posts, concerns: :searchable, constraints: { subdomain: "api" } do
  resources :comments, only: [:index, :create]
end

FAQ

What is the difference between namespace and scope?

Namespace changes both path and controller module. Scope allows customizing path or module independently.

Can I inspect routes from the console?

Yes. Rails.application.routes.routes or use the rails routes command.

How do I redirect old routes?

Use get 'old', to: redirect('/new') in routes.rb.

What is a mounted engine?

A Rails engine mounted at a path, like mount Blog::Engine, at: '/blog'.

How do I handle optional segments?

Use (/:optional) in route paths with defaults.

Mini Project: API with Versioned Routes

Build a versioned API routing structure.

Rails.application.routes.draw do
  constraints(subdomain: "api") do
    namespace :api do
      namespace :v1 do
        resources :products
        resources :orders, only: [:index, :show, :create]
      end
      namespace :v2 do
        resources :products
        resources :orders
      end
    end
  end
end

What's Next

Rails RESTful Routes Rails Controllers Deep Rails Params Strong Parameters

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro