After setting up my first Rails app, I was eager to start building features. But every tutorial I followed started with "add this to your routes file" and I had no idea what that meant or why it mattered.
If you're confused about Rails routing, this post will demystify how Rails connects URLs to your code and why good routing is the foundation of every Rails application.
What Are Routes, Really?
Think of routes as a receptionist for your Rails app. When someone visits a URL, routes decide which controller action should handle the request.
Here's the simple version: Routes map URLs to controller actions.
# config/routes.rb
Rails.application.routes.draw do
get '/about', to: 'pages#about'
end
This route says: "When someone visits /about
, send them to the about
action in the PagesController
."
My First Routing Confusion
When I started, I tried to access pages that didn't exist in my routes file. Rails would show me this error:
No route matches [GET] "/contact"
I didn't understand why Rails couldn't just find my contact.html.erb
file automatically. Coming from static HTML, this seemed unnecessarily complicated.
The lightbulb moment: Rails is dynamic. Unlike static HTML files, Rails routes can process data, check permissions, query databases, and generate content on-the-fly before showing you a page.
The Anatomy of a Route
Let's break down what a route actually contains:
get '/posts/:id', to: 'posts#show', as: 'post'
get
- The HTTP method (GET, POST, PUT, DELETE)'/posts/:id'
- The URL pattern (:id
is a parameter)'posts#show'
- Controller#action to handle the requestas: 'post'
- Creates a helper method (post_path
)
RESTful Routes (The Rails Way)
Rails encourages RESTful design, which sounds fancy but just means organizing your routes around resources. Instead of random URLs, you follow a pattern:
# The long way
get '/posts', to: 'posts#index'
get '/posts/new', to: 'posts#new'
post '/posts', to: 'posts#create'
get '/posts/:id', to: 'posts#show'
get '/posts/:id/edit', to: 'posts#edit'
patch '/posts/:id', to: 'posts#update'
delete '/posts/:id', to: 'posts#destroy'
# The Rails way
resources :posts
That single line resources :posts
creates all seven routes above automatically!
Understanding Route Parameters
Parameters let you capture parts of the URL and use them in your controller:
# Route
get '/users/:id', to: 'users#show'
# URL: /users/123
# params[:id] will be "123"
In your controller:
ruby
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
end
Route Helpers (URL Magic)
When you define routes, Rails automatically creates helper methods:
resources :posts
Creates these helpers:
- posts_path
→ /posts
- new_post_path
→ /posts/new
- post_path(@post)
→ /posts/123
- edit_post_path(@post)
→ /posts/123/edit
Use them in views instead of hardcoding URLs:
```erb
<!-- Good -->
<%= linkto "All Posts", postspath %>
<!-- Avoid -->
All Posts
```
Why helpers are better: If you change your routes later, helpers update automatically. Hardcoded URLs break.
Practical Examples From My Learning
1. A Simple Blog
# config/routes.rb
Rails.application.routes.draw do
root 'posts#index' # Homepage shows all posts
resources :posts # Standard blog routes
end
This gives you:
- GET /
→ Homepage with all posts
- GET /posts
→ List all posts
- GET /posts/new
→ Form to create new post
- POST /posts
→ Create new post
- GET /posts/123
→ Show specific post
- GET /posts/123/edit
→ Edit form for post
- PATCH /posts/123
→ Update post
- DELETE /posts/123
→ Delete post
2. Nested Routes (Posts with Comments)
resources :posts do
resources :comments, only: [:create, :destroy]
end
Creates routes like:
- POST /posts/123/comments
→ Create comment on post 123
- DELETE /posts/123/comments/456
→ Delete comment 456
3. Custom Routes for Special Actions
resources :posts do
member do
patch :publish # /posts/123/publish
patch :unpublish # /posts/123/unpublish
end
collection do
get :search # /posts/search
end
end
Common Routing Mistakes I Made
1. Forgetting the HTTP Method
# Wrong - only handles GET requests
get '/posts', to: 'posts#create'
# Right - POST for creating data
post '/posts', to: 'posts#create'
2. Parameter Naming Confusion
# In routes.rb
get '/posts/:post_id', to: 'posts#show'
# In controller - parameter name matches route
def show
@post = Post.find(params[:post_id]) # not params[:id]
end
3. Route Order Matters
# Wrong order - specific routes should come first
get '/posts/new', to: 'posts#new'
get '/posts/:id', to: 'posts#show'
# Right order
get '/posts/:id', to: 'posts#show'
get '/posts/new', to: 'posts#new' # This would never be reached
Wait, that's backwards! Let me fix that:
# Correct order - specific routes before parameterized ones
get '/posts/new', to: 'posts#new'
get '/posts/:id', to: 'posts#show'
Debugging Routes
Rails gives you tools to understand your routes:
# See all routes
rails routes
# Search for specific routes
rails routes | grep posts
# See routes for a specific controller
rails routes -c posts
Output looks like:
Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
post GET /posts/:id(.:format) posts#show
Testing Routes in the Console
You can test routes in the Rails console:
rails console
# Test route helpers
app.posts_path # "/posts"
app.post_path(1) # "/posts/1"
# Test route recognition
app.get "/posts/1" # Simulates GET request
Real-World Routing Example
Here's the routing for a simple task management app I built:
Rails.application.routes.draw do
root 'dashboard#index'
resources :tasks do
member do
patch :complete
patch :incomplete
end
end
resources :users, only: [:show, :edit, :update]
# Authentication
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
# Static pages
get '/about', to: 'pages#about'
get '/contact', to: 'pages#contact'
end
This creates a logical URL structure:
- /
→ Dashboard
- /tasks
→ All tasks
- /tasks/new
→ Create task
- /tasks/123/complete
→ Mark task as complete
- /login
→ Login form
- /about
→ About page
Route Constraints (Advanced)
You can add constraints to make routes more specific:
# Only match numeric IDs
get '/posts/:id', to: 'posts#show', constraints: { id: /\d+/ }
# Subdomain routing
constraints subdomain: 'api' do
resources :posts, defaults: { format: 'json' }
end
Best Practices I've Learned
- Use resources for standard CRUD operations - Don't reinvent the wheel
- Keep URLs simple and predictable - Users should be able to guess URLs
- Use route helpers everywhere - Never hardcode URLs
- Group related routes - Use namespaces and scopes for organization
- Test your routes - Use
rails routes
to verify what you've created
What's Next?
Understanding routes is crucial because they're the entry point to your application. Every user interaction starts with a route.
Next up in my Rails journey: diving into controllers and understanding how they process requests and prepare data for views.
Key takeaways:
- Routes map URLs to controller actions
- Use resources
for standard CRUD operations
- Route helpers keep your code flexible
- Order matters - specific routes before general ones
- Use rails routes
to debug and verify your routing
Have questions about routing? Drop them in the comments and I'll help clarify!
Next post: "My First Model: Building a Simple Task Manager" - Where we'll create our first database table and learn about ActiveRecord.