Basic routing question with HABTM

Hi, Rails newbie here.

If I have a basic HABTM association - say, users and groups - I can’t
get my head around the RESTful routing required to add a user to a
group.

POST /user will call user#create
POST /group will call group#create
POST /group/:group_id/user should call: what? Is it ok to define
a “addUser” action to the group controller? Or should I test for the
existence of the group_id in the user#create method and then proceed
accordingly? I want to do things the Rails way but sometimes my PHP
experience comes back to haunt me. :slight_smile:

Thanks,

Stan

I’m not sure what do you mean… but maybe this sample code will help
you…
:slight_smile:

resources :groups do
resources :users # using nested routes :slight_smile:
end

It will generate url like this
new_group_user GET /groups/:group_id/users/new(.:format)
{:action=>“new”, :controller=>“users”}

You can see the detail with “rake routes”

:slight_smile:

On Sat, Aug 20, 2011 at 7:35 PM, Stan McFarland <

Hi,

Thanks for responding, but that’s not really what I was looking
for. My basic problem is that I don’t understand how to correctly
distinguish between user creation and assignment of a user to a group
using RESTFUL routes. It appears to me that with nested routes, you
end up with users#create in both cases.

Stan

On 20 Aug 2011, at 13:35, Stan McFarland wrote:

experience comes back to haunt me. :slight_smile:
There is no one ‘correct’ way to do this. Both of your suggestions will
work. But I’d agree with your instinct that they both feel a little bit
hackish.

One solution would be to specify a different controller to handle users
scoped inside groups:

resources :groups do
resources :users, :controller => ‘group_users’
end

Then the concept of creating a user inside a group, and the concept of
creating a user, can be handled in completely separate controllers.

The problem with this is that you’ll be passing parameters like :user =>
{:name => “Bob S.”, :email => “[email protected]”, } to your
UsersController, while passing parameters like :user_id => 2 to your
GroupUsersController. It feels like theres some inconsistency there.

So you could invent a new concept, called a ‘membership’:

resources :groups do
resources :memberships
end

When a user joins a group, you’re not really creating a user – you’re
creating a membership. When a user leaves a group, you’re not really
deleting a user – you’re deleting a membership.

Note that a resource doesn’t have to match one-to-one with a
database-backed model. So you can expose this concept of a membership at
your controller level, and let the controllers deal with converting that
to model talk:

POST ‘/groups/1/memberships’, {:membership => {:user_id => 2}}

class MembershipsController < ActionController::Base
def create
@group = Group.find(params[:group_id])
@user = User.find(params[:membership][:user_id])
@group.users << @user
redirect_to wherever
end
end

Like I say, there isn’t a ‘correct’ way of handling this kind of thing,
but I personally like the idea of exposing the semantics of your
application like this, and trying to think of things in terms of CRUD
where possible.

Chris