RESTful habtm

(Note: using Rails 2.0.2)

I have users and groups, with a habtm association, and I want to provide a RESTful interface to adding and removing those associations. This is independent from creating and deleting users or groups. It also isn't quite as simple as treating the associations as resources, because I want to be 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 how 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   end end

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 end

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

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}

HTH, AndyV