mirror of
https://github.com/github/rails.git
synced 2026-04-26 03:00:59 -04:00
Expanded routing documentation with current best practices
This commit is contained in:
@@ -4,27 +4,26 @@ require 'active_support/core_ext/object/blank'
|
||||
require 'active_support/core_ext/class/attribute_accessors'
|
||||
|
||||
module ActionDispatch # :nodoc:
|
||||
# Represents an HTTP response generated by a controller action. One can use
|
||||
# an ActionDispatch::Response object to retrieve the current state
|
||||
# of the response, or customize the response. An Response object can
|
||||
# either represent a "real" HTTP response (i.e. one that is meant to be sent
|
||||
# back to the web browser) or a test response (i.e. one that is generated
|
||||
# from integration tests). See CgiResponse and TestResponse, respectively.
|
||||
# Represents an HTTP response generated by a controller action. Use it to
|
||||
# retrieve the current state of the response, or customize the response. It can
|
||||
# either represent a real HTTP response (i.e. one that is meant to be sent
|
||||
# back to the web browser) or a TestResponse (i.e. one that is generated
|
||||
# from integration tests).
|
||||
#
|
||||
# Response is mostly a Ruby on Rails framework implement detail, and
|
||||
# \Response is mostly a Ruby on \Rails framework implementation detail, and
|
||||
# should never be used directly in controllers. Controllers should use the
|
||||
# methods defined in ActionController::Base instead. For example, if you want
|
||||
# to set the HTTP response's content MIME type, then use
|
||||
# ActionControllerBase#headers instead of Response#headers.
|
||||
#
|
||||
# Nevertheless, integration tests may want to inspect controller responses in
|
||||
# more detail, and that's when Response can be useful for application
|
||||
# more detail, and that's when \Response can be useful for application
|
||||
# developers. Integration test methods such as
|
||||
# ActionDispatch::Integration::Session#get and
|
||||
# ActionDispatch::Integration::Session#post return objects of type
|
||||
# TestResponse (which are of course also of type Response).
|
||||
# TestResponse (which are of course also of type \Response).
|
||||
#
|
||||
# For example, the following demo integration "test" prints the body of the
|
||||
# For example, the following demo integration test prints the body of the
|
||||
# controller response to the console:
|
||||
#
|
||||
# class DemoControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
@@ -226,10 +226,24 @@ module ActionDispatch
|
||||
@set = set
|
||||
end
|
||||
|
||||
# You can specify what Rails should route "/" to with the root method:
|
||||
#
|
||||
# root :to => 'pages#main'
|
||||
#
|
||||
# You should put the root route at the end of <tt>config/routes.rb</tt>.
|
||||
def root(options = {})
|
||||
match '/', options.reverse_merge(:as => :root)
|
||||
end
|
||||
|
||||
# When you set up a regular route, you supply a series of symbols that
|
||||
# Rails maps to parts of an incoming HTTP request.
|
||||
#
|
||||
# match ':controller/:action/:id/:user_id'
|
||||
#
|
||||
# Two of these symbols are special: :controller maps to the name of a
|
||||
# controller in your application, and :action maps to the name of an
|
||||
# action within that controller. Anything other than :controller or
|
||||
# :action will be available to the action as part of params.
|
||||
def match(path, options=nil)
|
||||
mapping = Mapping.new(@set, @scope, path, options || {}).to_route
|
||||
@set.add_route(*mapping)
|
||||
@@ -258,22 +272,29 @@ module ActionDispatch
|
||||
end
|
||||
|
||||
module HttpHelpers
|
||||
# Define a route that only recognizes HTTP GET.
|
||||
def get(*args, &block)
|
||||
map_method(:get, *args, &block)
|
||||
end
|
||||
|
||||
# Define a route that only recognizes HTTP POST.
|
||||
def post(*args, &block)
|
||||
map_method(:post, *args, &block)
|
||||
end
|
||||
|
||||
# Define a route that only recognizes HTTP PUT.
|
||||
def put(*args, &block)
|
||||
map_method(:put, *args, &block)
|
||||
end
|
||||
|
||||
# Define a route that only recognizes HTTP DELETE.
|
||||
def delete(*args, &block)
|
||||
map_method(:delete, *args, &block)
|
||||
end
|
||||
|
||||
# Redirect any path to another path:
|
||||
#
|
||||
# match "/stories" => redirect("/posts")
|
||||
def redirect(*args, &block)
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
|
||||
@@ -314,12 +335,72 @@ module ActionDispatch
|
||||
end
|
||||
end
|
||||
|
||||
# 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
|
||||
module Scoping
|
||||
def initialize(*args) #:nodoc:
|
||||
@scope = {}
|
||||
super
|
||||
end
|
||||
|
||||
# Used to route <tt>/photos</tt> (without the prefix <tt>/admin</tt>)
|
||||
# to Admin::PostsController:
|
||||
#
|
||||
# scope :module => "admin" do
|
||||
# resources :posts
|
||||
# end
|
||||
def scope(*args)
|
||||
options = args.extract_options!
|
||||
options = options.dup
|
||||
@@ -441,6 +522,37 @@ module ActionDispatch
|
||||
end
|
||||
end
|
||||
|
||||
# Resource routing allows you to quickly declare all of the common routes
|
||||
# for a given resourceful controller. Instead of declaring separate routes
|
||||
# for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+
|
||||
# actions, a resourceful route declares them in a single line of code:
|
||||
#
|
||||
# resources :photos
|
||||
#
|
||||
# Sometimes, you have a resource that clients always look up without
|
||||
# referencing an ID. A common example, /profile always shows the profile of
|
||||
# the currently logged in user. In this case, you can use a singular resource
|
||||
# to map /profile (rather than /profile/:id) to the show action.
|
||||
#
|
||||
# resource :profile
|
||||
#
|
||||
# It's common to have resources that are logically children of other
|
||||
# resources:
|
||||
#
|
||||
# resources :magazines do
|
||||
# resources :ads
|
||||
# end
|
||||
#
|
||||
# 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
|
||||
#
|
||||
module Resources
|
||||
# CANONICAL_ACTIONS holds all actions that does not need a prefix or
|
||||
# a path appended since they fit properly in their scope level.
|
||||
@@ -549,6 +661,24 @@ module ActionDispatch
|
||||
@scope[:path_names].merge!(options)
|
||||
end
|
||||
|
||||
# Sometimes, you have a resource that clients always look up without
|
||||
# referencing an ID. A common example, /profile always shows the
|
||||
# profile of the currently logged in user. In this case, you can use
|
||||
# a singular resource to map /profile (rather than /profile/:id) to
|
||||
# the show action:
|
||||
#
|
||||
# resource :geocoder
|
||||
#
|
||||
# creates six different routes in your application, all mapping to
|
||||
# the GeoCoders controller (note that the controller is named after
|
||||
# the plural):
|
||||
#
|
||||
# GET /geocoder/new
|
||||
# POST /geocoder
|
||||
# GET /geocoder
|
||||
# GET /geocoder/edit
|
||||
# PUT /geocoder
|
||||
# DELETE /geocoder
|
||||
def resource(*resources, &block)
|
||||
options = resources.extract_options!
|
||||
|
||||
@@ -578,6 +708,22 @@ module ActionDispatch
|
||||
self
|
||||
end
|
||||
|
||||
# In Rails, a resourceful route provides a mapping between HTTP verbs
|
||||
# and URLs and controller actions. By convention, each action also maps
|
||||
# to particular CRUD operations in a database. A single entry in the
|
||||
# routing file, such as
|
||||
#
|
||||
# resources :photos
|
||||
#
|
||||
# creates seven different routes in your application, all mapping to
|
||||
# the Photos controller:
|
||||
#
|
||||
# GET /photos/new
|
||||
# POST /photos
|
||||
# GET /photos/:id
|
||||
# GET /photos/:id/edit
|
||||
# PUT /photos/:id
|
||||
# DELETE /photos/:id
|
||||
def resources(*resources, &block)
|
||||
options = resources.extract_options!
|
||||
|
||||
@@ -608,6 +754,18 @@ module ActionDispatch
|
||||
self
|
||||
end
|
||||
|
||||
# To add a route to the collection:
|
||||
#
|
||||
# resources :photos do
|
||||
# collection do
|
||||
# get 'search'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# This will enable Rails to recognize paths such as <tt>/photos/search</tt>
|
||||
# with GET, and route to the search action of PhotosController. It will also
|
||||
# create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
|
||||
# route helpers.
|
||||
def collection
|
||||
unless @scope[:scope_level] == :resources
|
||||
raise ArgumentError, "can't use collection outside resources scope"
|
||||
@@ -618,6 +776,17 @@ module ActionDispatch
|
||||
end
|
||||
end
|
||||
|
||||
# To add a member route, add a member block into the resource block:
|
||||
#
|
||||
# resources :photos do
|
||||
# member do
|
||||
# get 'preview'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# This will recognize <tt>/photos/1/preview</tt> with GET, and route to the
|
||||
# preview action of PhotosController. It will also create the
|
||||
# <tt>preview_photo_url</tt> and <tt>preview_photo_path</tt> helpers.
|
||||
def member
|
||||
unless resource_scope?
|
||||
raise ArgumentError, "can't use member outside resource(s) scope"
|
||||
|
||||
@@ -17,7 +17,7 @@ module ActionDispatch
|
||||
#
|
||||
# == Usage within the framework
|
||||
#
|
||||
# Polymorphic URL helpers are used in a number of places throughout the Rails framework:
|
||||
# Polymorphic URL helpers are used in a number of places throughout the \Rails framework:
|
||||
#
|
||||
# * <tt>url_for</tt>, so you can use it with a record as the argument, e.g.
|
||||
# <tt>url_for(@article)</tt>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module ActionDispatch
|
||||
module Routing
|
||||
# In <b>routes.rb</b> one defines URL-to-controller mappings, but the reverse
|
||||
# In <tt>config/routes.rb</tt> you define URL-to-controller mappings, but the reverse
|
||||
# is also possible: an URL can be generated from one of your routing definitions.
|
||||
# URL generation functionality is centralized in this module.
|
||||
#
|
||||
@@ -12,15 +12,14 @@ module ActionDispatch
|
||||
#
|
||||
# == URL generation from parameters
|
||||
#
|
||||
# As you may know, some functions - such as ActionController::Base#url_for
|
||||
# As you may know, some functions, such as ActionController::Base#url_for
|
||||
# and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
|
||||
# of parameters. For example, you've probably had the chance to write code
|
||||
# like this in one of your views:
|
||||
#
|
||||
# <%= link_to('Click here', :controller => 'users',
|
||||
# :action => 'new', :message => 'Welcome!') %>
|
||||
#
|
||||
# # Generates a link to /users/new?message=Welcome%21
|
||||
# # => "/users/new?message=Welcome%21"
|
||||
#
|
||||
# link_to, and all other functions that require URL generation functionality,
|
||||
# actually use ActionController::UrlFor under the hood. And in particular,
|
||||
@@ -61,7 +60,7 @@ module ActionDispatch
|
||||
#
|
||||
# UrlFor also allows one to access methods that have been auto-generated from
|
||||
# named routes. For example, suppose that you have a 'users' resource in your
|
||||
# <b>routes.rb</b>:
|
||||
# <tt>config/routes.rb</tt>:
|
||||
#
|
||||
# resources :users
|
||||
#
|
||||
|
||||
@@ -115,8 +115,8 @@ module ActionDispatch
|
||||
end
|
||||
end
|
||||
|
||||
# An integration Session instance represents a set of requests and responses
|
||||
# performed sequentially by some virtual user. Because you can instantiate
|
||||
# An instance of this class represents a set of requests and responses
|
||||
# performed sequentially by a test process. Because you can instantiate
|
||||
# multiple sessions and run them side-by-side, you can also mimic (to some
|
||||
# limited extent) multiple simultaneous users interacting with your system.
|
||||
#
|
||||
@@ -373,12 +373,12 @@ module ActionDispatch
|
||||
end
|
||||
end
|
||||
|
||||
# An IntegrationTest is one that spans multiple controllers and actions,
|
||||
# An test that spans multiple controllers and actions,
|
||||
# tying them all together to ensure they work together as expected. It tests
|
||||
# more completely than either unit or functional tests do, exercising the
|
||||
# entire stack, from the dispatcher to the database.
|
||||
#
|
||||
# At its simplest, you simply extend IntegrationTest and write your tests
|
||||
# At its simplest, you simply extend <tt>IntegrationTest</tt> and write your tests
|
||||
# using the get/post methods:
|
||||
#
|
||||
# require "test_helper"
|
||||
@@ -403,7 +403,7 @@ module ActionDispatch
|
||||
# However, you can also have multiple session instances open per test, and
|
||||
# even extend those instances with assertions and methods to create a very
|
||||
# powerful testing DSL that is specific for your application. You can even
|
||||
# reference any named routes you happen to have defined!
|
||||
# reference any named routes you happen to have defined.
|
||||
#
|
||||
# require "test_helper"
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user