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

> 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. :)

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 Smith", :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

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to