Routing

Ruby on Rails Fundamentals — Routing
Ruby on Rails Fundamentals
Course 1 · Chapter 2 · Routing

🛤️ Routing

Chapter 1's generator briefly added a single route entry as a side effect. This chapter covers config/routes.rb properly — and specifically the single line, resources :posts, that replaces an entire file's worth of Express route definitions with one declaration.

📄 config/routes.rb

Rails.application.routes.draw do get "welcome/index" # more routes go here end

Every route in a Rails app is declared inside this one file, inside the draw block — a single source of truth, unlike Express's routes potentially spread across multiple router files mounted together (as Chapter 1's comparison showed).

⚡ resources :posts — Seven Routes, One Line

Rails.application.routes.draw do resources :posts end

This single line generates all seven conventional RESTful routes for the Post resource. Run rails routes to see exactly what got created:

$ rails routes -c posts Prefix Verb URI Pattern Controller#Action posts GET /posts posts#index POST /posts posts#create new_post GET /posts/new posts#new edit_post GET /posts/:id/edit posts#edit post GET /posts/:id posts#show PATCH /posts/:id posts#update PUT /posts/:id posts#update DELETE /posts/:id posts#destroy

Seven distinct actions, mapped to conventional URLs and HTTP verbs, generated entirely from one word: :posts. Rails infers the controller name (PostsController, from Chapter 1), the pluralization, and every URL pattern from that single symbol.

📜 The Same Seven Routes — Rails vs Express

One Line vs a Full File

Express (from Chapter 1's example)Rails
router.route('/').get(controller.list).post(controller.create);
router.route('/:id').get(controller.show).patch(controller.update).delete(controller.remove);
(plus new/edit routes, if the app renders server-side forms)
resources :posts

Express requires every verb/path/handler combination spelled out explicitly — genuinely more visible and traceable, but genuinely more typing, and easy to have drift out of sync with REST conventions over time. Rails' single line is faster to write and impossible to get inconsistent, at the cost of needing to already know what those seven routes actually are.

🔗 Named Route Helpers

posts_path # => "/posts" post_path(5) # => "/posts/5" new_post_path # => "/posts/new" edit_post_path(5) # => "/posts/5/edit"

resources :posts also generates named path helpers, visible as the Prefix column in the rails routes output above. Instead of hardcoding "/posts/#{id}/edit" as a string throughout the app — the way you'd typically build a URL in Express, string-interpolating a path directly — Rails gives you a real method call. Rename the route later, and every call site using the helper updates automatically; every hardcoded string wouldn't.

🪆 Nested Resources

Rails.application.routes.draw do resources :posts do resources :comments # nested under posts end end # generates, among others: # GET /posts/:post_id/comments comments#index # POST /posts/:post_id/comments comments#create

Nesting resources :comments inside resources :posts generates comment routes scoped under a specific post's ID — the Rails equivalent of Express's router.use('/posts/:postId/comments', commentsRouter) pattern, again collapsed to a declarative block instead of manual router mounting.

🎯 Limiting and Customizing Routes

resources :posts, only: [:index, :show] # just these two, nothing else resources :posts, except: [:destroy] # all seven except deleting resources :posts do member do post "publish" # POST /posts/:id/publish -- acts on ONE post end collection do get "drafts" # GET /posts/drafts -- acts on the whole collection end end
⚠ Custom, non-RESTful routes need more ceremony, not less

Here's a genuine reversal of this course's usual pattern: adding one extra Express route is a single router.post(...) line, no ceremony at all. Adding a non-standard Rails route requires understanding member vs collection blocks first — member for routes acting on one specific resource (needs an :id), collection for routes acting on the resource as a whole (no :id). Rails' conventions make the common case (the seven standard actions) dramatically shorter, but the moment you step outside them, you're learning Rails-specific concepts Express simply doesn't require.

💻 Coding Challenges

Challenge 1: Generate and List Routes

Write the single routes.rb line for a fully RESTful articles resource, then write out, in a table or list, all seven routes you'd expect rails routes to show — verb, path, and controller#action for each.

Goal: Memorize the seven standard REST routes well enough to predict them without running the command.

→ Solution

Challenge 2: Convert Express Routes to Rails

Given this Express setup — router.get('/products', ...), router.get('/products/:id', ...), router.post('/products', ...) only, with no update or delete routes at all — write the equivalent single-line Rails routes.rb entry using only: to match exactly this reduced set of actions.

Goal: Practice recognizing when only:/except: is the right tool rather than a bare resources line.

→ Solution

Challenge 3: Nested Resources Plus a Member Route

Write a routes.rb that nests resources :reviews under resources :products, and adds a custom member route, POST /products/:id/feature, that maps to a feature action on ProductsController.

Goal: Combine nested resources and a custom member route in one realistic routes file.

→ Solution

💎 Where the "Magic" Actually Pays Off

Chapter 1 warned that convention over configuration can feel confusing before it clicks. Named route helpers are a clean, concrete example of where it pays off clearly: edit_post_path(@post) reads as intent ("the edit URL for this post") rather than a hardcoded, easy-to-typo string, and it stays correct automatically if the underlying URL structure ever changes. This is the kind of small, compounding ergonomic win the rest of this course will keep surfacing.

🎯 What's Next

Next chapter: Controllers & Actions — writing the seven conventional action methods routing actually calls, working with params, and how Rails' controller layer compares to Express's request handlers.