Makcheese Makcheese - 1 year ago 55
Ruby Question

Polymorphic Routes with Custom Actions in Rails

So I am making a chat app, and I want users to be able to leave chat rooms. This would be done by posting a delete request to a route like


The Users model has
has_many :chat_rooms, through: chat_room_users
while ChatRooms has
has_many :users, through chat_room_users
. The UsersController has a
action, which I want to call using this request on this url.

I want to create a link to this url on a view that I have. I already have a variable
for the current user and
for the current chat room available on the view. So how would I do a link_to and route for this setup? I have
delete /users/:id/chat_rooms/leave/:chat_room_id
in the routes.rb file, but how would I do the link_to?

Thank you.

max max
Answer Source

You're overcomplicating it.

DELETE /chat_rooms/:chat_room_id/leave

Instead of passing the user id via the URL you should instead get it through the session or a token (if its an API app).

Rule of thumb: resources should never be nested more than 1 level deep. A collection may need to be scoped by its parent, but a specific member can always be accessed directly by an id, and shouldn’t need scoping (unless the id is not unique, for some reason).

This is just a loose example of how to solve this:

# routes.rb
resources :chat_rooms do
  member do
    post :join
    delete :leave

class User
  has_many :chat_room_users 
  has_many :chat_rooms, though: :chats

class ChatRoomUser
  belongs_to :user
  belongs_to :chatroom

class ChatRoom
  has_many :chats
  has_many :users, though: :chats

Putting this in UsersController is pretty questionable. I would instead place it in ChatroomsController.

class ChatroomsController   
  # ...
  # POST /chat_rooms/:chat_room_id/join
  def join
    @chat_room = ChatRoom.find(params[:id])
    @chat = @chat_room)

    if @chat_room.create
      # ...
      # ...
  # DELETE /chat_rooms/:chat_room_id/leave
  def leave
    @chat_room = ChatRoom.find(params[:id])
    @chat = current_user.chat_room_users.find_by(chat_room: @chat_room)

<%= button_to 'Join', join_chat_room_path(@chat_room), method: :post %>
<%= button_to 'Leave', leave_chat_room_path(@chat_room), method: :delete %>
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download