I have two models, Player and Event. A player can subscribe to several
events and a event has several participants (players). Therefore, it
is a many-to-many relationship. My question now is how do I have to
implement this many-to-many relationship using the REST approach.
I do not need to store additional information in the bridge table
(let's call it "subscriptions" or "events_players"), therefore I added
"has_and_belongs_to_many" to the player and the events model. What I
am now missing is a "subscribe" action, that I would normally stick
into the player controller, but this violates the REST pattern,
because it is not a CRUD action.
The only way around this, that I see, is to make subscription a full
blown model with its own RESTful controller. This would give me CRUD
operations on "subscriptions", with new/create being the equivalent to
a subscribe action, correct?
Is it therefore correct to say, that "has_and_belongs_to_many" cannot
be used in RESTful applications?
To retain a fully RESTful interface, you need a subscriptions
controller. If there isn't any other "extra" information on the
subscriptions controller, you could simply create a subscribe method
or whatever on one of the models, but typically in REST design, you'd
create an independent controller.
Isn't one of the advantages of using REST that this automatically
creates an easy to use API? If I introduce "non-standard" commands,
wouldn't that break the conventions?
Where do you see the advantages / disadvantages for adding to an
existing controller versus creating a "many-to-many" controller?
Controllers don't necessarily have a 1:1 mapping to models. For
example, you could quite easily have
class RegistrationsController < ActionController::Base
def create
e = Event.find(params[:id])
current_user.events << e
flash[:success] = "You've registered for #{e.name}"
redirect_to user_home_url
end
end
You've got an easy to use API, and your model code can stay how it is.
If your model changes to store extra attributes on the registration,
the API stays the same (except for passing in extra, perhaps optional,
attributes). It's also flexible and obvious how to extend it if/when
you want to treat registrations as a resource of their own.