skip to content

Resources & Seven Actions

One resources line yields seven actions with fixed verbs, paths and named helpers; only:, except: and a singular resource trim it. Interviewers ask for the table and when to add a controller instead.

part ofRuby on Railsoverview, primer and where to startread it →
on this pageshow

explore

questions

5

In config/routes.rb, which seven routes does resources :photos generate, with their HTTP verbs, paths, controller actions and named helpers?

level: juniorimportance: must knowfreq 85%

answer

  1. four helper names, seven actions
  2. collection vs member paths
  3. new drawn before :id
  4. update answers PATCH and PUT
  5. each route takes (.:format)

basics

~10 s

resources :photos draws index and create on /photos, new on /photos/new, and show, edit, update and destroy on /photos/:id, all handled by PhotosController, with helpers photos_path, new_photo_path, edit_photo_path and photo_path.

solid answer

~30 s

One `resources :photos` line maps seven actions of `PhotosController`. The collection path `/photos` takes `GET` for `index` and `POST` for `create`; `GET /photos/new` is `new`; the member path `/photos/:id` takes `GET` for `show`, `PATCH` and `PUT` for `update`, and `DELETE` for `destroy`; `GET /photos/:id/edit` is `edit`. Only four helper names come out of it: `photos_path` (index and create), `new_photo_path`, `edit_photo_path(photo)` and `photo_path(photo)` (show, update, destroy), each with a `_url` twin. Every path also accepts an optional `(.:format)`, and the id arrives as `params[:id]`.

code

ruby · 4 lines
ruby
# config/routes.rb
Rails.application.routes.draw do
  resources :photos
end

go deeper

for a junior

Recite the seven rows: verb, path, action and helper. Group them into collection routes, member routes and the new form, and remember that only four helper names exist.

for a middle

Explain why helpers are per path rather than per verb, why new must be drawn before the :id route, and what the optional format segment adds to every path.

for a senior

Use the table to reason about requests that miss: a trimmed new falling through to show, an undefined action answering 404, and what API-only mode removes.

for a principal

Treat the seven actions as a team contract that generators, forms and reviewers rely on, and push back on routes that bypass it without a reason.

## What one resources line does In a Rails application the router reads `config/routes.rb` from top to bottom and builds a table of **routes**: each pairs an HTTP verb and a path pattern with a `controller#action` and, usually, a **named route** that generates the URL back. Writing those lines one by one is possible (`get "photos/:id", to: "photos#show"`), but the everyday form is a **resourceful route**: ```ruby Rails.application.routes.draw do resources :photos end ``` For a photography-portfolio site that single line draws every route the photo pages need, all mapped to `PhotosController`. ## The table interviewers expect | Verb | Path | Action | Helper | |---|---|---|---| | GET | `/photos` | `index` | `photos_path` | | GET | `/photos/new` | `new` | `new_photo_path` | | POST | `/photos` | `create` | `photos_path` | | GET | `/photos/:id` | `show` | `photo_path(photo)` | | GET | `/photos/:id/edit` | `edit` | `edit_photo_path(photo)` | | PATCH / PUT | `/photos/:id` | `update` | `photo_path(photo)` | | DELETE | `/photos/:id` | `destroy` | `photo_path(photo)` | Read it as two groups: - **Collection routes** act on the set of photos and carry no id: `index` lists them, `create` adds one. - **Member routes** act on one photo and carry `:id`: `show`, `edit`, `update` and `destroy`. - `new` is the odd one out: a form page for a photo that does not exist yet, so it sits under the collection path with a fixed `new` segment. The `:id` segment arrives in the controller as `params[:id]`, a string. The router does not check that a record exists; it only matches the pattern. ## Helpers: four names, two flavours The seven actions share **four route names**, because a name belongs to a path, not to a verb: 1. `photos` covers `GET` and `POST /photos`. 2. `new_photo` covers `GET /photos/new`. 3. `edit_photo` covers `GET /photos/:id/edit`. 4. `photo` covers `GET`, `PATCH`, `PUT` and `DELETE /photos/:id`. Each name defines a `_path` helper (a relative path such as `/photos/7`) and a `_url` helper (the full URL with host). The verb is chosen by whatever sends the request, such as a form or a `button_to`, not by the helper. ## PATCH and PUT both reach update Rails draws **two routes** for `update`: one for `PATCH` and one for `PUT`, both on `/photos/:id`. `bin/rails routes` lists them on separate lines. Rails' own forms submit `PATCH` for an existing record, so `PUT` is there for clients that send a full replacement; both land in the same action, and the controller cannot tell from the route which one arrived unless it reads `request.method`. ## Details that come up as follow-ups - **Order matters.** The router tries routes in the order they were drawn, and `resources` draws `new` before `show`, so `/photos/new` reaches `new` instead of `show` with `params[:id] == "new"`. - **Format segment.** Every path ends in an optional `(.:format)`, so `/photos/7.json` reaches `show` with `params[:format] == "json"`. - **API-only apps.** With `config.api_only = true`, `resources` drops `new` and `edit`, because a JSON client needs no HTML form pages; five actions remain. - **Missing actions.** The routes exist whether or not the controller defines the methods. A request to a route whose action is neither defined nor backed by a template raises `AbstractController::ActionNotFound`, which answers 404. ## Mistakes interviewers listen for | Belief | What `resources :photos` actually draws | |---|---| | Every action has its own helper | Four names: `photos`, `new_photo`, `edit_photo`, `photo` | | `POST /photos/:id` updates | `POST` exists only on `/photos`, for `create` | | Update is `PUT` only | Both `PATCH` and `PUT` reach `update` | | The controller is `PhotoController` | It is the plural `PhotosController` | | The router checks the record exists | It matches the pattern; the action's lookup decides | ## Why the convention matters The seven actions are a contract shared by the router, the controllers, the form helpers and other developers. Anyone who knows the table can read `resources :photos` and know which URLs exist, which method handles each, and which helper builds each link, without opening the controller. Interviewers ask for the table because so much of the framework assumes it: - `form_with` picks `POST` or `PATCH` according to whether the record is new, and expects these routes to exist. - `redirect_to @photo` resolves through the `photo` route name. - The scaffold generator writes a controller with exactly these seven methods. A route table that departs from the seven actions is not wrong, but every departure is something the next developer has to look up.

  • Why does GET /photos/new not reach show with params[:id] set to "new"?
    Routes match in the order they are drawn, and `resources` draws the `new` route before the member routes. `/photos/new` therefore matches `GET /photos/new` first. If `new` is removed with `only:` or `except:`, the same request falls through to `GET /photos/:id` and reaches `show` with `params[:id] == "new"`.
  • What changes in the table when the app was generated with --api?
    With `config.api_only = true`, `resources :photos` draws five actions: `index`, `create`, `show`, `update` and `destroy`. The `new` and `edit` routes, and their `new_photo_path` and `edit_photo_path` helpers, are not drawn, because they exist only to serve HTML forms.

saying these in an interview costs you the question

  • resources :photos defines a separate helper name for every one of the seven actions
  • Updates must be sent with PUT because Rails only routes PUT to update
  • POST /photos/:id is the route that updates a photo
  • The router checks that the photo exists before calling show
  • resources :photos routes to a PhotoController class
open as a page

In config/routes.rb, how do only: and except: trim resources :photos, and what happens to a request for an action you removed?

level: middleimportance: must knowfreq 62%

basics

~20 s

only: keeps the listed actions and except: drops them; the removed routes and their helpers are simply not drawn. A request for a removed route raises ActionController::RoutingError (404), unless another route, such as GET /photos/:id, matches it first.

open as a page

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%

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.

open as a page

In config/routes.rb, how does resource :profile differ from resources :profiles in routes, helpers and the controller it calls?

level: middleimportance: should knowfreq 55%

basics

~20 s

resource :profile draws six routes on /profile with no :id and no index, names helpers profile_path, new_profile_path and edit_profile_path, and still routes to the plural ProfilesController; the action finds the record from context, not params.

open as a page

In a Rails app where photos are published and unpublished, why route to a separate resourceful controller instead of adding publish and unpublish actions to PhotosController?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Modelling publishing as a resource, resource :publication under each photo, maps publish to create and unpublish to destroy on a small controller, so every controller keeps to the seven actions and the routes stay predictable.

open as a page