Routers

You can route REST Framework controllers with the regular Rails routing helpers, but the framework provides three dedicated routers (rest_root, rest_route, rest_resource, and rest_resources) that introspect the controller and wire up extra actions, built-in actions, and bulk routes automatically.

Routing the API Root

Your API root typically explains how to authenticate and provides a description of the API.

The recommended pattern is a dedicated RootController inside the api namespace, so root-specific actions and configuration don’t propagate through inheritance to every descendant resource controller:

app/controllers/
├── api/
│   ├── groups_controller.rb
│   ├── movies_controller.rb
│   ├── root_controller.rb
│   └── users_controller.rb
├── api_controller.rb
└── application_controller.rb
Rails.application.routes.draw do
  namespace :api do
    rest_root  # Finds Api::RootController and routes `#root` to '/'.
    rest_resources :movies
    rest_resources :users
  end
end

rest_root accepts a controller name override (rest_root :home would route Api::HomeController#root to /api/) and an action: kwarg (rest_root action: :welcome would route Api::RootController#welcome).

Resourceful Routing

rest_resource (singular) and rest_resources (plural) are analogous to Rails’ resource and resources, but they add three things:

  1. They skip built-in CRUD actions that are excluded via excluded_actions or for which the controller isn’t configured (e.g., a controller without model skips all CRUD actions).
  2. They route every extra_actions entry on the collection and every extra_member_actions entry on the member.
  3. If the controller has bulk = true, they route update_all (PATCH/PUT /resource) and destroy_all (DELETE /resource). Bulk create (array POSTs) uses the regular create route. Bulk actions can be individually opted out through excluded_actions.
Rails.application.routes.draw do
  namespace :api do
    rest_root
    rest_resource :user       # Singular: no :id in URLs, no #index route.
    rest_resources :movies    # Plural: includes the full CRUD set.
  end
end

Overriding Plurality with singleton_controller

A controller can force singular or plural routing regardless of which helper routes it:

class Api::UserController < ApiController
  self.model = User
  self.singleton_controller = true   # Always render singular routes.
end

Passing Options

rest_resource / rest_resources accept the same options as Rails’ resource(s), including only:, except:, path:, as:, and controller:. Options are forwarded through.

rest_resources :movies, path: "films", as: "films"

Unscoped Nested Blocks

Normally, a block passed to rest_resources is auto-scoped to the resource’s module/path. Pass unscoped: true to disable the scope:

rest_resources :movies, unscoped: true do
  # Routes here won't be nested under /movies/:movie_id.
end

Non-resourceful Routing

rest_route does not route the standard REST actions (index, show, create, update, destroy). Only extra_actions defined on the controller get routed (plus options, since the framework supports OPTIONS-based metadata). Use it for singleton API endpoints like a network status or health check:

class Api::NetworkController < ApiController
  self.extra_actions = { ping: :get, stats: :get }

  def ping
    render(api: { status: "ok" })
  end

  def stats
    render(api: { ... })
  end
end
Rails.application.routes.draw do
  namespace :api do
    rest_root
    rest_route :network
  end
end

Routing Behavior Details