RESTful habtm

(Note: using Rails 2.0.2)

I have users and groups, with a habtm association, and I want to provide
RESTful interface to adding and removing those associations. This is
independent from creating and deleting users or groups. It also isn’t
as simple as treating the associations as resources, because I want to
able to provide an interface to all of the following:

  • add a user to a group
  • remove a user from a group
  • add a group to a user
  • remove a group from a user
  • set the list of users in a group
  • set the list of groups a user is in

I believe this is a use case for nested resources, but I’m not clear on
to go about it either in terms of routing or in the controller.
Would someone explain how to go about it?


The purpose of nesting resources is to say ‘it only makes sense to
retrieve this object through this other object’. A simple example is
for a Blog – it only makes sense to access the comments through the
post to which they are attached. In the case of the blog you could
do something like this in routes.rb:

map.resources :blogs do |blog|
blog.resources :posts do |post|
post.resources :comments

There are some very strong feelings out in the community about how
deeply you should nest resources. As a practical matter it becomes a
real pain in the neck to deal with things if you nest more than a
level or two deep. Along those lines, you are allowed to create
multiple entries in the routes.rb for each controller so you could
break down the code above as follows:

map.resources :blogs do |blog|
blog.resources :posts

map.resources :posts do |post|
post.resources :comments

In either case you’ll have named routes along the lines of
<outer_controller>_<inner_controller>_path …

blog_post_path(@blog, @post) – get to an individual post
blog_posts_path(@blog) – get to the collection of posts for a
particular blog

It’d also be completely acceptable from a REST perspective to consider
the User and Group resources to include their habtm relationship.
What I mean is that you could perfectly well create actions for
add_group, set_group, and remove_group to your UsersController if you
find that simplifies things. In that case you would extend the route
mapping with member functions (you specify the name followed by the
http verb):

map.resources :users, :member=>{:add_group=>:post,
:remove_group=>:delete, :set_group=>:put}

On Apr 13, 10:35 am, Gregory S. [email protected]