module ActionDispatch::Routing::Mapper::Scoping

def constraints(constraints = {})

end
resources :iphones
constraints(Iphone) do

This class is then used like this:

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

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

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

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

Requests to routes can be constrained based on specific criteria:

=== Dynamic request matching

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

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

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

=== Restricting based on IP

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

You may use this to also restrict other parameters:

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

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

For instance, in order to change the routes to allow for a dot character in the +id+ parameter:
Allows you to constrain the nested routes based on a set of rules.
=== Parameter Restriction
def constraints(constraints = {})
  scope(:constraints => constraints) { yield }
end

def controller(controller, options={})

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

Scopes routes to a specific controller
def controller(controller, options={})
  options[:controller] = controller
  scope(options) { yield }
end

def defaults(defaults = {})

Using this, the +:id+ parameter here will default to 'home'.
end
match 'scoped_pages/(:id)', :to => 'pages#show'
defaults :id => 'home' do
Allows you to set default parameters for a route, such as this:
def defaults(defaults = {})
  scope(:defaults => defaults) { yield }
end

def merge_as_scope(parent, child) #:nodoc:

:nodoc:
def merge_as_scope(parent, child) #:nodoc:
  parent ? "#{parent}_#{child}" : child
end

def merge_blocks_scope(parent, child) #:nodoc:

:nodoc:
def merge_blocks_scope(parent, child) #:nodoc:
  merged = parent ? parent.dup : []
  merged << child if child
  merged
end

def merge_constraints_scope(parent, child) #:nodoc:

:nodoc:
def merge_constraints_scope(parent, child) #:nodoc:
  merge_options_scope(parent, child)
end

def merge_controller_scope(parent, child) #:nodoc:

:nodoc:
def merge_controller_scope(parent, child) #:nodoc:
  child
end

def merge_defaults_scope(parent, child) #:nodoc:

:nodoc:
def merge_defaults_scope(parent, child) #:nodoc:
  merge_options_scope(parent, child)
end

def merge_module_scope(parent, child) #:nodoc:

:nodoc:
def merge_module_scope(parent, child) #:nodoc:
  parent ? "#{parent}/#{child}" : child
end

def merge_options_scope(parent, child) #:nodoc:

:nodoc:
def merge_options_scope(parent, child) #:nodoc:
  (parent || {}).except(*override_keys(child)).merge(child)
end

def merge_path_names_scope(parent, child) #:nodoc:

:nodoc:
def merge_path_names_scope(parent, child) #:nodoc:
  merge_options_scope(parent, child)
end

def merge_path_scope(parent, child) #:nodoc:

:nodoc:
def merge_path_scope(parent, child) #:nodoc:
  Mapper.normalize_path("#{parent}/#{child}")
end

def merge_shallow_path_scope(parent, child) #:nodoc:

:nodoc:
def merge_shallow_path_scope(parent, child) #:nodoc:
  Mapper.normalize_path("#{parent}/#{child}")
end

def merge_shallow_prefix_scope(parent, child) #:nodoc:

:nodoc:
def merge_shallow_prefix_scope(parent, child) #:nodoc:
  parent ? "#{parent}_#{child}" : child
end

def merge_shallow_scope(parent, child) #:nodoc:

:nodoc:
def merge_shallow_scope(parent, child) #:nodoc:
  child ? true : false
end

def namespace(path, options = {})

end
resources :posts
namespace :admin, :as => "sekret" do
# generates +sekret_posts_path+ rather than +admin_posts_path+

end
resources :posts
namespace :admin, :module => "sekret" do
# maps to Sekret::PostsController rather than Admin::PostsController

end
resources :posts
namespace :admin, :path => "sekret" do
# accessible through /sekret/posts rather than /admin/posts

=== Examples

Resources#resources.
For options, see Base#match. For +:shallow_path+ option, see

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

=== Options

admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
admin_post PUT /admin/posts/:id(.:format) admin/posts#update
admin_post GET /admin/posts/:id(.:format) admin/posts#show
edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
new_admin_post GET /admin/posts/new(.:format) admin/posts#new
admin_posts POST /admin/posts(.:format) admin/posts#create
admin_posts GET /admin/posts(.:format) admin/posts#index

This generates the following routes:

end
resources :posts
namespace :admin do

Scopes routes to a specific namespace. For example:
def namespace(path, options = {})
  path = path.to_s
  options = { :path => path, :as => path, :module => path,
              :shallow_path => path, :shallow_prefix => path }.merge!(options)
  scope(options) { yield }
end

def override_keys(child) #:nodoc:

:nodoc:
def override_keys(child) #:nodoc:
  child.key?(:only) || child.key?(:except) ? [:only, :except] : []
end

def scope(*args)

end
resources :posts
scope :as => "sekret" do
# prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+

end
resources :posts
scope :path => "/admin" do
# prefix the posts resource's requests with '/admin'

end
resources :posts
scope :module => "admin" do
# route /posts (without the prefix /admin) to Admin::PostsController

=== Examples

Takes same options as Base#match and Resources#resources.

=== Options

rather than /accounts/:account_id/projects.
The difference here being that the routes generated are like /:account_id/projects,
This generates helpers such as +account_projects_path+, just like +resources+ does.

end
resources :projects
scope :path => ":account_id", :as => "account" do

Take the following route definition as an example:

Scopes a set of routes to the given default options.
def scope(*args)
  options = args.extract_options!
  options = options.dup
  options[:path] = args.first if args.first.is_a?(String)
  recover = {}
  options[:constraints] ||= {}
  unless options[:constraints].is_a?(Hash)
    block, options[:constraints] = options[:constraints], {}
  end
  scope_options.each do |option|
    if value = options.delete(option)
      recover[option] = @scope[option]
      @scope[option]  = send("merge_#{option}_scope", @scope[option], value)
    end
  end
  recover[:block] = @scope[:blocks]
  @scope[:blocks] = merge_blocks_scope(@scope[:blocks], block)
  recover[:options] = @scope[:options]
  @scope[:options]  = merge_options_scope(@scope[:options], options)
  yield
  self
ensure
  scope_options.each do |option|
    @scope[option] = recover[option] if recover.has_key?(option)
  end
  @scope[:options] = recover[:options]
  @scope[:blocks]  = recover[:block]
end

def scope_options #:nodoc:

:nodoc:
def scope_options #:nodoc:
  @scope_options ||= private_methods.grep(/^merge_(.+)_scope$/) { $1.to_sym }
end