Datasheet
Chapter 1: Building Resources
10
are well named. But if you get into things like user_address_street_house_room_url(x, y, z,
a, b)
, it could get a little hairy. There are a couple of ways to clean those long method names up:
The arguments to the URL or path method can be entered as key/value pairs:
recipe_ingredient_url(:recipe_id = > @recipe, :id = > @ingredient)
For URLs, the url_for method can be used (remember to specify the HTTP method if needed):
url_for(@recipe, @ingredient)
Either choice should help tame unclear route method calls.
Customizing Resource Routes
The resources call in the routes.rb file can also be customized to adjust the behavior of the routes.
The most common reason for doing this is to add your own actions to the resource. Each resource call
provides three options for specifying custom actions. The
:member option is for actions that apply to a
specific resource, the
:collection option is for actions on the entire list (like index ), and the :new
option applies to resources that have not yet been saved to the database. In each case, the value for
each option is itself a hash. The keys of that hash are the method names, and the values are the HTTP
verbs to be used when calling that method. So, if you wanted to add a print action to your recipes, it
would look like this:
map.resources :recipes, :method = > {:print = > :get } do |recipes|
recipes.resources :ingredients
end
The addition here of :method = > {:print = > :get } creates the new print action, and tells Rails
that this action will be defined on a specific resource called via
GET . The URL of this new action will be /
recipes/1/print
. (This is a change from older versions of Rails, where this used to be spelled /
recipes/1;print
— nobody really liked the semicolon syntax, and it tended to interfere with caching,
so it was changed for Rails 2.0.)
The URL for a collection - based action would look like
/recipes/ < action > , and the URL for a new -
based action would be
/recipes/new/ < action > .
What ’ s more, you also get a URL and path method for the new action. In this case, they would be
print_recipe_path(@recipe) and print_recipe_url(@recipe) .
The tricky thing about these custom routes is remembering to specify them. Unlike nearly everything
else in Rails, a custom resource route needs to be specified twice: once in the controller itself, and then
again in
routes.rb . This is arguably a violation of one of Rails core design principles, namely Don ’ t
Repeat Yourself (DRY), and it ’ s entirely possible that somebody clever will come along and clean this up
at sometime in the future.
Like most of Rails, the standard names can be overridden if you like. In the case of a resource routing
call, there are a few options to change standard naming. You can specify an arbitrary controller class to
be the target of the resource with the
:controller option. You can change the name of the controller
within the URL (the
recipe in /recipe/1 ) using the :singular option, and you can require a prefix to
the URL with the
:path_prefix option. The prefix passed to that option works just the same way as a
❑
❑
c01.indd 10c01.indd 10 1/30/08 4:02:23 PM1/30/08 4:02:23 PM