Mudassir Ali
Mudassir Ali

Reputation: 8041

RESTful way of Adding / Removing has-many-through associations

I have the following models

class User < ActiveRecord::Base
  has_many :user_wishes
  has_many :wishes, through: :user_wishes
end
 
class UserWish < ActiveRecord::Base
  belongs_to :user
  belongs_to :wish
end
 
class Wish < ActiveRecord::Base
  has_many :user_wishes
  has_many :users, through: :user_wishes
end

Now I have the following interface, where the user can select / deselect the wishes.

Wish List

Once the user is done with the selection/deselection, he submits the form. Now all I do in the backend is create or destroy user_wishes records for the given user_id & wish_id.

There are now two ways to implement this solution that I could think of.

1. By Calculating the difference between existing & new wishes

Say the user already has N wishes, now he makes a new request with M wishes. I'll delete the difference of (N - M) and add the difference of (M - N). This approach seems very inefficient since I always have to send (N ∩ M) via network.

Endpoint: /user_wishes
TYPE: POST ? but it also deletes records
Params: {wish_id: [1,2 ..], user_id: 10}

2. By sending only the changed ones

I'll have logic on the frontend which gives me a list of newly added/removed wishes.

Endpoint: /user_wishes
TYPE: POST ? but it also deletes records
Params: {added_wish_ids: [1,2 ..], removed_wish_ids: [12, 16], user_id: 10}

I'm using this approach right now but this doesn't seem RESTful to me !

I'd like to know what is the best way to go about this. What endpoint should this go and what should be the request type ?

Upvotes: 3

Views: 1215

Answers (1)

eabraham
eabraham

Reputation: 4164

Probably the most restful method of adding/deleting these wishes would be to have a nested api structure with separate POST and DELETE calls.

POST   /user/:user_id/wish/:wish_id
DELETE /user/:user_id/wish/:wish_id

As a user checks/un-checks an item off the list it would send POST/DELETE respectively.

class UserWishController < ApplicationController
  def create
    user_id = params[:user_id]
    wish_id = params[:wish_id]

    UserWish.create(user_id: user_id, wish_id: wish_id)
  end

  def destroy
    user_id = params[:user_id]
    wish_id = params[:wish_id]

    uw = UserWish.find(user_id: user_id, wish_id: wish_id)
    uw.destroy if uw.present?
  end
end

Upvotes: 5

Related Questions