In config/routes.rb, what do the path:, as:, controller:, param: and path_names: options each change on resources :photos?
answer
- URL, helper name, class, key
- path: moves the URL only
- as: renames helpers only
- param: renames :id everywhere
- path_names: touches new and edit
basics
~20 spath: 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 sEach 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# 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 controllergo deeper
Match each option to the one thing it changes: URL, helper names, controller class, parameter name, or the new and edit words.
Explain how the options compose, why uncountable names get an _index collection route, and how param: changes nested parent keys too.
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.
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