Module ActionDispatch::Routing::Mapper::Scoping
In: lib/action_dispatch/routing/mapper.rb

You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an admin namespace. You would place these controllers under the app/controllers/admin directory, and you can group them together in your router:

  namespace "admin" do
    resources :posts, :comments
  end

This will create a number of routes for each of the posts and comments controller. For Admin::PostsController, Rails will create:

  GET       /admin/photos
  GET       /admin/photos/new
  POST    /admin/photos
  GET       /admin/photos/1
  GET       /admin/photos/1/edit
  PUT       /admin/photos/1
  DELETE  /admin/photos/1

If you want to route /photos (without the prefix /admin) to Admin::PostsController, you could use

  scope :module => "admin" do
    resources :posts, :comments
  end

or, for a single case

  resources :posts, :module => "admin"

If you want to route /admin/photos to PostsController

(without the Admin:module prefix), you could use
  scope "/admin" do
    resources :posts, :comments
  end

or, for a single case

  resources :posts, :path => "/admin"

In each of these cases, the named routes remain the same as if you did not use scope. In the last case, the following paths map to PostsController:

  GET       /admin/photos
  GET       /admin/photos/new
  POST    /admin/photos
  GET       /admin/photos/1
  GET       /admin/photos/1/edit
  PUT       /admin/photos/1
  DELETE  /admin/photos/1

Methods

Public Instance methods

Parameter Restriction

Allows you to constrain the nested routes based on a set of rules. For instance, in order to change the routes to allow for a dot character in the id parameter:

  constraints(:id => /\d+\.\d+) do
    resources :posts
  end

Now routes such as +/posts/1+ will no longer be valid, but +/posts/1.1+ will be. The id parameter must match the constraint passed in for this example.

You may use this to also resrict other parameters:

  resources :posts do
    constraints(:post_id => /\d+\.\d+) do
      resources :comments
    end

Restricting based on IP

Routes can also be constrained to an IP or a certain range of IP addresses:

  constraints(:ip => /192.168.\d+.\d+/) do
    resources :posts
  end

Any user connecting from the 192.168.* range will be able to see this resource, where as any user connecting outside of this range will be told there is no such route.

Dynamic request matching

Requests to routes can be constrained based on specific critera:

   constraints(lambda { |req| req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do
     resources :iphones
   end

You are able to move this logic out into a class if it is too complex for routes. This class must have a +matches?+ method defined on it which either returns true if the user should be given access to that route, or false if the user should not.

   class Iphone
     def self.matches(request)
       request.env["HTTP_USER_AGENT"] =~ /iPhone/
     end
   end

An expected place for this code would be +lib/constraints+.

This class is then used like this:

   constraints(Iphone) do
     resources :iphones
   end

Scopes routes to a specific controller

Example:

  controller "food" do
    match "bacon", :action => "bacon"
  end

Allows you to set default parameters for a route, such as this: defaults :id => ‘home’ do

  match 'scoped_pages/(:id)', :to => 'pages#show'

end Using this, the +:id+ parameter here will default to ‘home’.

Scopes routes to a specific namespace. For example:

  namespace :admin do
    resources :posts
  end

This generates the following routes:

    admin_posts GET    /admin/posts(.:format)          {:action=>"index", :controller=>"admin/posts"}
    admin_posts POST   /admin/posts(.:format)          {:action=>"create", :controller=>"admin/posts"}
 new_admin_post GET    /admin/posts/new(.:format)      {:action=>"new", :controller=>"admin/posts"}

edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"}

     admin_post GET    /admin/posts/:id(.:format)      {:action=>"show", :controller=>"admin/posts"}
     admin_post PUT    /admin/posts/:id(.:format)      {:action=>"update", :controller=>"admin/posts"}
     admin_post DELETE /admin/posts/:id(.:format)      {:action=>"destroy", :controller=>"admin/posts"}

Supported options

The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ all default to the name of the namespace.

:path
The path prefix for the routes.

namespace :admin, :path => "sekret" do

  resources :posts

end

All routes for the above resources will be accessible through +/sekret/posts+, rather than +/admin/posts+

:module
The namespace for the controllers.

namespace :admin, :module => "sekret" do

  resources :posts

end

The PostsController here should go in the Sekret namespace and so it should be defined like this:

class Sekret::PostsController < ApplicationController

  # code go here

end

:as
Changes the name used in routing helpers for this namespace.
  namespace :admin, :as => "sekret" do
    resources :posts
  end

Routing helpers such as admin_posts_path will now be sekret_posts_path.

:shallow_path
See the scope method.

Used to route /photos (without the prefix /admin) to Admin::PostsController:

Supported options

:module
If you want to route /posts (without the prefix /admin) to Admin::PostsController, you could use
  scope :module => "admin" do
    resources :posts
  end
:path
If you want to prefix the route, you could use
  scope :path => "/admin" do
    resources :posts
  end

This will prefix all of the posts resource‘s requests with ’/admin‘

:as
Prefixes the routing helpers in this scope with the specified label.
  scope :as => "sekret" do
    resources :posts
  end

Helpers such as posts_path will now be sekret_posts_path

[:shallow_path]

  Prefixes nested shallow routes with the specified path.

  scope :shallow_path => "sekret" do
    resources :posts do
      resources :comments, :shallow => true
    end

  The +comments+ resource here will have the following routes generated for it:

    post_comments    GET    /sekret/posts/:post_id/comments(.:format)
    post_comments    POST   /sekret/posts/:post_id/comments(.:format)
    new_post_comment GET    /sekret/posts/:post_id/comments/new(.:format)
    edit_comment     GET    /sekret/comments/:id/edit(.:format)
    comment          GET    /sekret/comments/:id(.:format)
    comment          PUT    /sekret/comments/:id(.:format)
    comment          DELETE /sekret/comments/:id(.:format)

[Validate]