Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1

214 | Chapter 7: REST, Resources, and Web Services


The named routes will only be recognized given the proper HTT Pmethod; if called
with other methods, they will return 404:


>> app.deactivate_person_path(1)
=> "/people/1/deactivate"
>> app.post app.deactivate_person_path(1)
=> 200
>> app.get app.deactivate_person_path(1)
=> 404

Note that defining custom routes like this can easily deviate from REST. It is easy to
overload a resource with many custom methods that may better be factored into
resources of their own. For example, rather than POSTing to/people/1/deactivate,
the RESTful action would be either to PUTactive=0to/people/1or toPUTa value of
0 to/people/1/active, depending on whetheractivewas modeled as a separate
resource or an attribute of the person resource. It is intentional that custom routes
are a bit unpleasant to use, because most of the application domain should be mod-
eled with CRUD and special cases should be the exception rather than the rule.


Nested resource routes


Rails has a provision to specify nested resources when generating named routes. For
example, consider a social networking application where each person can have many
friends; we can express these resource relationships with the nested route declaration:


map.resources :people do |person|
person.resources :friends
end

In this situation, the friends resources are scoped to a particular person. The URI for
a friend belonging to a person would look like/people/1/friends/2, and a person’s
friends could be viewed at/people/1/friends.


The corresponding named routes are simple, with one minor change: they take an
extra parameter, for theperson_idto which they are scoped. Given that route decla-
ration, we now have the following routes (note that the declaration also includes the
basepeople resources).


Note that we are still in a flat controller namespace. By default, those route declara-
tions will look forPeopleControllerandFriendsController. If the resources are truly


Named route URI Controller Params
people_path /people people {}
person_path(1) /people/1 people {:id => 1}
friends_path(1) /people/1/friends friends {:person_id => 1}
friend_path(1, 2) /people/1/friends/2 friends {:person_id => 1, :id => 2}
Free download pdf