Ruby on Rails Scoping routes


Example

Rails provides several ways to organize your routes.

Scope by URL:

scope 'admin' do
  get 'dashboard', to: 'administration#dashboard'
  resources 'employees'
end

This generates the following routes

get       '/admin/dashboard',          to: 'administration#dashboard'
post      '/admin/employees',          to: 'employees#create'
get       '/admin/employees/new',      to: 'employees#new'
get       '/admin/employees/:id/edit', to: 'employees#edit'
get       '/admin/employees/:id',      to: 'employees#show'
patch/put '/admin/employees/:id',      to: 'employees#update'
delete    '/admin/employees/:id',      to: 'employees#destroy'

It may make more sense, on the server side, to keep some views in a different subfolder, to separate admin views from user views.

Scope by module

scope module: :admin do
  get 'dashboard', to: 'administration#dashboard'
end

module looks for the controller files under the subfolder of the given name

get       '/dashboard',          to: 'admin/administration#dashboard'

You can rename the path helpers prefix by adding an as parameter

scope 'admin', as: :administration do
  get 'dashboard'
end

# => administration_dashboard_path

Rails provides a convenient way to do all the above, using the namespace method. The following declarations are equivalent

namespace :admin do
end

scope 'admin', module: :admin, as: :admin

Scope by controller

scope controller: :management do
  get 'dashboard'
  get 'performance'
end

This generate these routes

get       '/dashboard',          to: 'management#dashboard'
get       '/performance',        to: 'management#performance'

Shallow Nesting

Resource routes accept a :shallow option that helps to shorten URLs where possible. Resources shouldn't be nested more than one level deep. One way to avoid this is by creating shallow routes. The goal is to leave off parent collection URL segments where they are not needed. The end result is that the only nested routes generated are for the :index , :create , and :new actions. The rest are kept in their own shallow URL context. There are two options for scope to custom shallow routes:

  • :shallow_path: Prefixes member paths with a specified parameter

    scope shallow_path: "sekret" do
      resources :articles do
        resources :comments, shallow: true
      end
    end
    
  • :shallow_prefix: Add specified parameters to named helpers

    scope shallow_prefix: "sekret" do
      resources :articles do
        resources :comments, shallow: true
      end
    end
    

We can also illustrate shallow routes more by:

resources :auctions, shallow: true do
  resources :bids do
   resources :comments
  end
end 

alternatively coded as follows (if you’re block-happy):

resources :auctions do
 shallow do
   resources :bids do
     resources :comments
   end
 end
end

The resulting routes are:

PrefixVerbURI Pattern
bid_commentsGET/bids/:bid_id/comments(.:format)
POST/bids/:bid_id/comments(.:format)
new_bid_commentGET/bids/:bid_id/comments/new(.:format)
edit_commentGET/comments/:id/edit(.:format)
commentGET/comments/:id(.:format)
PATCH/comments/:id(.:format)
PUT/comments/:id(.:format)
DELETE/comments/:id(.:format)
auction_bidsGET/auctions/:auction_id/bids(.:format)
POST/auctions/:auction_id/bids(.:format)
new_auction_bidGET/auctions/:auction_id/bids/new(.:format)
edit_bidGET/bids/:id/edit(.:format)
bidGET/bids/:id(.:format)
PATCH/bids/:id(.:format)
PUT/bids/:id(.:format)
DELETE/bids/:id(.:format)
auctionsGET/auctions(.:format)
POST/auctions(.:format)
new_auctionGET/auctions/new(.:format)
edit_auctionGET/auctions/:id/edit(.:format)
auctionGET/auctions/:id(.:format)
PATCH/auctions/:id(.:format)
PUT/auctions/:id(.:format)
DELETE/auctions/:id(.:format)

If you analyze the routes generated carefully, you’ll notice that the nested parts of the URL are only included when they are needed to determine what data to display.