skip to content

In config/routes.rb, what do the path:, as:, controller:, param: and path_names: options each change on resources :photos?

level: middleimportance: should knowfreq 40%

answer

  1. URL, helper name, class, key
  2. path: moves the URL only
  3. as: renames helpers only
  4. param: renames :id everywhere
  5. path_names: touches new and edit

basics

~20 s

path: changes the URL prefix, as: changes the helper names, controller: changes the controller class, param: renames the :id segment and params key, and path_names: renames the new and edit URL segments; each leaves the others untouched.

solid answer

~30 s

Each option moves one axis of the generated routes. `path: "gallery"` serves `/gallery` and `/gallery/:id` but keeps `photos_path` and `PhotosController`. `as: "images"` renames the helpers to `images_path`, `image_path` and `new_image_path` while URLs stay `/photos`. `controller: "images"` dispatches to `ImagesController` with URLs and helpers unchanged; in Rails 8.1 a misspelt controller answers 500, not 404. `param: :slug` turns `/photos/:id` into `/photos/:slug`, so the action reads `params[:slug]`, and it may not contain a colon. `path_names: { new: "upload", edit: "change" }` renames just those two segments; helper and action names stay the same.

code

ruby · 9 lines
ruby
# config/routes.rb
Rails.application.routes.draw do
  resources :photos, path: "gallery", param: :slug,
                     path_names: { new: "upload" }
end

# GET /gallery/upload  -> photos#new   new_photo_path
# GET /gallery/:slug   -> photos#show  photo_path(photo)
# params[:slug] holds the segment in the controller

go deeper

for a junior

Match each option to the one thing it changes: URL, helper names, controller class, parameter name, or the new and edit words.

for a middle

Explain how the options compose, why uncountable names get an _index collection route, and how param: changes nested parent keys too.

for a senior

Use these options to change public URLs without touching code, check every combination with bin/rails routes, and know that a missing controller now surfaces as a 500.

for a principal

Agree team rules for when URLs may diverge from code names, since every divergence is a lookup cost for the next reader.

## Three axes of a resourceful route Every route that `resources :photos` draws in `config/routes.rb` has three names derived from the symbol `:photos`: - the **URL path**: `/photos`, `/photos/:id`; - the **route name** behind the helpers: `photos_path`, `photo_path`, `new_photo_path`, `edit_photo_path`; - the **controller**: `PhotosController`. A fourth name is the **dynamic segment** `:id`, which becomes `params[:id]`. The options on `resources` let you change one of these without touching the others, which is what keeps a URL redesign from rippling through every template and controller. ## The options side by side | Option | Example | URL | Helpers | Controller | Param | |---|---|---|---|---|---| | (none) | `resources :photos` | `/photos/:id` | `photo_path` | `PhotosController` | `params[:id]` | | `path:` | `path: "gallery"` | `/gallery/:id` | `photo_path` | `PhotosController` | `params[:id]` | | `as:` | `as: "images"` | `/photos/:id` | `image_path` | `PhotosController` | `params[:id]` | | `controller:` | `controller: "images"` | `/photos/:id` | `photo_path` | `ImagesController` | `params[:id]` | | `param:` | `param: :slug` | `/photos/:slug` | `photo_path` | `PhotosController` | `params[:slug]` | ## path: `path:` replaces the URL segment. A portfolio that wants public URLs under `/gallery` while the code keeps talking about photos writes `resources :photos, path: "gallery"`. Every route moves, including `/gallery/new` and `/gallery/:id/edit`, and every `photo_path(photo)` call starts producing the new URL without edits. ## as: `as:` renames the **route names**, and with them every helper: `resources :photos, as: "images"` gives `images_path`, `image_path`, `new_image_path` and `edit_image_path`, while URLs stay `/photos`. It is the tool when a generated name collides with another route or reads badly. Naming has one automatic special case, for **uncountable** words: `resources :equipment` cannot tell its collection from its member by name, so Rails names the collection route `equipment_index` and the member route `equipment`. ## controller: `controller:` points the routes at a different class: `controller: "images"` dispatches to `ImagesController`. URLs and helpers are untouched. Since Rails 8.1.0, if the class does not exist the request answers **500**, not 404, because a route to a missing controller is a programming error rather than a request for a missing page; the exception is `ActionDispatch::MissingController`. ## param: `param:` renames the dynamic segment. With `param: :slug` the member paths become `/photos/:slug` and the action reads `params[:slug]`. Two details: 1. The value may not contain a colon; `param: :"photo:slug"` raises `ArgumentError`. 2. Routes nested inside the block get a parent key built from it, `:photo_slug` instead of `:photo_id`. Renaming the segment does not change what a helper puts in it: `photo_path(photo)` still asks the record for its URL parameter, so the model must supply the slug for links to match. ## path_names: `path_names:` renames the fixed `new` and `edit` URL segments: ```ruby resources :photos, path_names: { new: "upload", edit: "change" } # GET /photos/upload -> photos#new new_photo_path # GET /photos/:id/change -> photos#edit edit_photo_path ``` Helper names and action names stay as they were; only the visible URL words change, which is the usual reason to use it (a translated or friendlier segment). ## Why change one axis at a time Each option exists because the three names serve different readers: - **Visitors and search engines** see the URL, so marketing may want `/gallery` or a translated word while the code says photos. - **Template authors** call the helpers, so a collision or an awkward generated name is fixed with `as:` without moving any URL. - **Maintainers** see the controller class, so a reorganised `app/controllers` tree is handled with `controller:` while links keep working. Changing the symbol itself, say to `resources :gallery_items`, would rename all three at once and force edits across templates, controllers and tests. The options are how you avoid that ripple. ## Combining them The options compose: `resources :photos, path: "gallery", controller: "portfolio/photos", param: :slug` gives `/gallery/:slug`, served by `Portfolio::PhotosController`, with `photo_path` helpers. Anything else passed to `resources`, such as `module:` or `defaults:`, is turned into a wrapping `scope`, which belongs to the scoping part of the DSL. Verify a combination with `bin/rails routes -c photos` rather than by reasoning alone.

  • A photographer site adds resources :equipment. Why does bin/rails routes show equipment_index?
    `equipment` is uncountable in Active Support's inflections, so its singular and plural are the same word. Rails would give the collection and member routes the same name, so it appends `_index` to the collection: `equipment_index_path` for index and create, `equipment_path(item)` for the member routes. `as:` can choose different names.
  • After a refactor, resources :photos, controller: "gallery_photos" points at a class that was renamed. What does a request get in Rails 8.1?
    The router still matches, but loading `GalleryPhotosController` fails, raising `ActionDispatch::MissingController`. Since Rails 8.1.0 that is not treated as a routing error, so the response is a 500 and the error is reported, where earlier versions answered 404 and hid the mistake.

saying these in an interview costs you the question

  • as: "images" also moves the URLs to /images
  • path: changes the helper names to match the new URL
  • path_names: { new: "upload" } renames the helper to upload_photo_path
  • param: :slug keeps the controller reading params[:id]
  • A misspelt controller: in Rails 8.1 answers 404 like any unknown URL