2.5 Scoping Routing Rules
Rails gives you a variety of ways to bundle together related routing rules concisely. They’re all based on usage of the scope
method and its various shortcuts.
get 'auctions/new' => 'auctions#new'
get 'auctions/edit/:id' => 'auctions#edit'
post 'auctions/pause/:id' => 'auctions#pause'
# Can Dry up with the scope method
scope controller: :auctions do
get 'auctions/new' => :new
get 'auctions/edit/:id' => :edit post 'auctions/pause/:id' => :pause
end
# DRY it up by adding the :path argument to scope
scope path: '/auctions', controller: :auctions do
get 'new' => :new
get 'edit/:id' => :edit
post 'pause/:id' => :pause
end
2.5.1 Controller
The scope method accepts a :controller
option (or it can interpret a symbol as its first argument to assume a controller).
scope controller: :auctions do
scope :auctions do
# to make it obvious, use the controller method instead of scope
controller :auction do
2.5.2 Path Prefix
The scope method accepts a :path
option (or it can interpret a string as its first parameter to mean a path prefix).
scope path: '/auction' do
scope 'auction' do
# in Rails 4, pass the :path option symbols instead of strings
scope :acutions, :archived do
# cope all routes nested under it to the “/auctions/archived” path.
2.5.3 Name Prefix
The scope method also accepts a :as
option that affects the way that named route URL helper methods are generated.
# will generate a named URL helper method called admin_new_auction_url
scope :auctions, as: 'admin' do
get 'new' => :new, as: 'new_auction'
end
2.5.4 Namespaces
URLs can be grouped by using the namespace
method, which is syntactic sugar that rolls up module, name prefix and path prefix settings into one declaration. The implementation of the namespace method
converts its first argument into a string, which is why in some example code you’ll see it take a symbol.
namespace :auctions, :controller => :auctions do
get 'new' => :new
get 'edit/:id' => :edit
post 'pause/:id' => :pause
end
2.5.5 Bundling Contraints
If you find yourself repeating similar segment key constraints in related routes, you can bundle them together using the :constraints
option of the scope
method:
# It’s likely that only a subset of rules in a given scope need constraints applied to them.
scope controller: :auctions, constraints: {:id => /\d+/ } do
get 'edit/:id' => :edit
post 'pause/:id' => :pause
end
scope path: '/auctions', controller: :auctions do
get 'new' => :new
constraints id: /\d+/ do
get 'edit/:id' => :edit
post 'pause/:id' => :pause
end
end
To enable modular reuse, you may supply the constraints method with an object that has a matches?
method.
class DateFormatConstraint
def self.matches?(request)
request.params[:date] =~ /\A\d{4}-\d\d-\d\d\z/ # YYYY-MM-DD
end
end
# in routes.rb
constraints(DateFormatConstraint) do
get 'since/:date' => :since
end