Question

Rails Collection Routes vs Member Routes Explained

rubyruby-on-rails

Question

What is the difference between member routes and collection routes in Ruby on Rails?

For example, what is the difference between these two route definitions?

resources :photos do
  member do
    get :preview
  end
end
resources :photos do
  collection do
    get :search
  end
end

I do not understand when to use each type of route or how their generated URLs differ.

Short Answer

By the end of this page, you will understand that a member route acts on one existing resource and includes its id, while a collection route acts on the resource list and does not require an id. You will also know how to define, recognize, and use both in Rails controllers and views.

Concept

Rails resource routing starts with the idea that a route usually represents a resource, such as a photo.

resources :photos

This creates standard routes for creating, listing, showing, updating, and deleting photos. Sometimes an application needs an action that is not one of Rails' standard RESTful actions.

For example:

  • Preview one specific photo.
  • Search across all photos.

Rails provides member and collection blocks for these cases.

A member route operates on one specific record. Because Rails must know which record to use, its URL includes an identifier such as :id.

GET /photos/42/preview

A collection route operates on the entire set of records. It does not target one particular photo, so its URL has no :id.

GET /photos/search

This distinction matters because it determines:

  • the URL Rails creates,
  • whether params[:id] is available,
  • whether the controller action should load one record,
  • which route helper Rails generates.

Use these routes only when the action genuinely fits the resource. If an action represents a separate resource or a complex workflow, a separate controller and resource may be clearer.

Mental Model

Think of photos as a photo album.

  • A member route is an action on one photograph you picked up from the album: “preview photo 42.” Rails needs to know which photograph, so the URL includes its ID.
  • A collection route is an action on the album as a whole: “search the photo album.” Rails does not need a single photo ID.

In short:

  • Member = one item.
  • Collection = the whole group of items.
Take Quiz

Syntax and Examples

A member route is declared inside member do ... end.

resources :photos do
  member do
    get :preview
  end
end

Rails creates a route similar to:

GET /photos/:id/preview

The controller action can use params[:id] to find the requested photo.

class PhotosController < ApplicationController
  def preview
    @photo = Photo.find(params[:id])
  end
end

The corresponding route helper takes a photo or ID:

preview_photo_path(@photo)
# => "/photos/42/preview"

A collection route is declared inside collection do ... end.

resources :photos do
  collection do
    get :search
  end
end

Rails creates a route similar to:

GET /photos/search

There is no photo ID in this URL. The controller commonly reads a query parameter instead.

class PhotosController < ApplicationController
  def search
    @photos = Photo.where("title LIKE ?", "%#{params[:q]}%")
  end
end

The route helper does not need a photo argument:

search_photos_path(q: "sunset")
# => "/photos/search?q=sunset"

For a single custom route, Rails also supports a shorter form:

resources :photos do
  get :preview, on: :member
  get :search, on: :collection
end

Step by Step Execution

Consider these routes:

resources :photos do
  get :preview, on: :member
  get :search, on: :collection
end

Request 1: previewing one photo

GET /photos/12/preview
  1. Rails matches /photos/12/preview to the member route.

  2. Rails sets params[:id] to "12".

  3. Rails calls PhotosController#preview.

  4. The action finds the one photo:

    @photo = Photo.find(params[:id])
    
  5. The response can render a preview for photo 12.

Request 2: searching photos

GET /photos/search?q=beach
  1. Rails matches /photos/search to the collection route.

  2. No photo ID is present, so params[:id] is nil.

  3. Rails sets params[:q] to "beach".

  4. Rails calls PhotosController#search.

  5. The action searches the full photo collection:

    @photos = Photo.where("title LIKE ?", "%#{params[:q]}%")
    
  6. The response renders a list of matching photos.

Real World Use Cases

Good member route examples

These actions need one existing record:

  • GET /orders/15/invoice — download or view one order's invoice.
  • POST /articles/9/publish — publish one draft article.
  • PATCH /users/7/activate — activate one user account.
  • POST /payments/31/refund — refund one payment.
  • GET /documents/4/download — download one document.

Good collection route examples

These actions apply to a group of records or provide a collection-level interface:

  • GET /products/search?q=keyboard — search all products.
  • GET /orders/recent — show recent orders.
  • GET /reports/summary — show a summary across all reports.
  • POST /users/import — import multiple users from a file.
  • GET /articles/archive — show an archive of articles.

The key question is: Would the request still make sense without selecting one record first? If yes, it is often a collection action.

Take Quiz

Real Codebase Usage

In real Rails applications, custom actions should be named clearly and kept small. The controller usually follows a different pattern for each route type.

Member action: load one record first

A before_action is common when several actions require the same record.

class PhotosController < ApplicationController
  before_action :set_photo, only: [:show, :edit, :update, :destroy, :preview]

  def preview
    render :preview
  end

  private

  def set_photo
    @photo = Photo.find(params[:id])
  end
end

Collection action: filter or query records

Collection actions often use query parameters, pagination, and filtering.

class PhotosController < ApplicationController
  def search
    @photos = Photo.order(created_at: :desc)
    @photos = @photos.where("title LIKE ?", "%#{params[:q]}%") if params[:q].present?
  end
end

Authorization

Authorization often follows the same distinction:

  • Member action: authorize a particular record, such as authorize @photo.
  • Collection action: authorize access to the resource type or query scope.

Prefer RESTful resources when an action becomes substantial

For example, if “publishing” has its own data, history, permissions, and lifecycle, it may be better modeled as a resource instead of a custom member action.

resources :articles do
  resource :publication, only: [:create, :destroy]
end

This produces routes such as POST /articles/:article_id/publication, which can be easier to extend and test.

Common Mistakes

Expecting params[:id] in a collection action

This collection route has no :id segment:

resources :photos do
  get :search, on: :collection
end

So this is incorrect:

# Broken: params[:id] is nil for /photos/search
@photo = Photo.find(params[:id])

Use a member route when the action needs a specific photo.

resources :photos do
  get :preview, on: :member
end

Forgetting to pass an object to a member helper

# Broken: Rails needs to know which photo to preview.
preview_photo_path

Pass a record or an ID:

preview_photo_path(@photo)
preview_photo_path(42)

Passing a record to a collection helper

# Usually incorrect and unnecessary.
search_photos_path(@photo)

A collection action does not identify one photo. Pass search options instead:

search_photos_path(q: "mountains")

Using a collection route for an action on one record

# Wrong shape for “preview one photo”
resources :photos do
  collection do
    get :preview
  end
end

This creates /photos/preview, with no way to identify the photo through the path. Use member.

Creating too many custom actions

Routes such as approve, reject, archive, reopen, and publish can be valid. But a controller with many unrelated custom actions can signal that the domain needs another resource. Consider whether the action creates or manages something with its own state and behavior.

Comparisons

FeatureMember routeCollection route
Acts onOne existing resourceThe resource set as a whole
URL pattern/photos/:id/action/photos/action
Example URL/photos/42/preview/photos/search
params[:id]AvailableNot supplied by the route
Helperpreview_photo_path(@photo)search_photos_path
Typical purposePreview, publish, archive, downloadSearch, import, recent, summary

Member route versus nested resource

A member action is suitable for a small operation directly related to a resource:

post :publish, on: :member

A nested resource is often better when the operation has its own data or lifecycle:

resources :articles do
  resources :comments
end

For example, a comment is not merely an action called comment; it is a resource that can be created, listed, edited, and deleted.

member block versus on: :member

These definitions are equivalent:

resources :photos do
  member do
    get :preview
  end
end
resources :photos do
  get :preview, on: :member
end

Use the block form when defining several routes of the same kind. Use on: when defining one route concisely.

Take Quiz

Cheat Sheet

# Standard RESTful routes
resources :photos

# One photo: URL includes :id
resources :photos do
  get :preview, on: :member
end
# GET /photos/:id/preview
# preview_photo_path(@photo)
# params[:id]

# All photos: URL has no :id
resources :photos do
  get :search, on: :collection
end
# GET /photos/search
# search_photos_path(q: "term")
# params[:id] is nil
  • Use member when the action requires one existing record.
  • Use collection when the action applies to the list or resource type.
  • A member helper needs a record or ID.
  • A collection helper normally takes only query parameters or request data.
  • Run bin/rails routes to inspect the exact route names and URL patterns.

FAQ

What is a member route in Rails?

A member route is a custom route that acts on one resource record. Its path includes :id, such as /photos/42/preview.

What is a collection route in Rails?

A collection route is a custom route that acts on the entire resource collection. Its path has no resource ID, such as /photos/search.

Does a member route always use GET?

No. Choose the HTTP verb based on the operation. GET is appropriate for reading, while POST, PATCH, or DELETE may be appropriate for state changes.

resources :articles do
  post :publish, on: :member
end

Why does preview_photo_path require a photo argument?

The member route includes :id, so Rails needs a record or ID to construct the URL.

preview_photo_path(@photo)

Why does search_photos_path not require a photo?

A collection route does not contain :id; it targets the photo collection. You can optionally provide query parameters.

search_photos_path(q: "forest")

Can collection routes accept parameters?

Yes. They can receive query parameters, form data, or JSON request bodies. They simply do not receive a resource ID from their route pattern.

How can I see the routes Rails generated?

Run this command in your Rails project:

bin/rails routes

It shows the HTTP verb, URL pattern, controller action, and route helper name.

Take Quiz

Mini Project

Description

Build custom routes for a small photo library. Visitors should be able to search the entire library, while an individual photo page should provide a preview action. This demonstrates how URL structure determines whether an action works with one record or a collection.

Goal

Create a PhotosController with a collection search action and a member preview action.

Requirements

  1. Define photos as a Rails resource.
  2. Add a GET collection route named search.
  3. Add a GET member route named preview.
  4. Implement search so it filters photos by an optional q query parameter.
  5. Implement preview so it loads one photo from params[:id].
Take Quiz

Keep learning

Related questions

View more