Reputation: 570
I am creating a RESTful API to be consumed by n+ clients over HTTP.
If I have a Users <= Friendships => Friends many-to-many relationship, should I be satisfied that in order to DELETE any of a User's Friendships, I will first have to query GET friendships#index to get the ID of the friendship that I intend to DELETE, and then issue the DELETE request?
GET /friendships?user_id=123&friend_id=456
=> {id:"999",user_id:"123",friend_id:"456"}
DELETE /friendships/999
=> "Friendship deleted"
In order for a User to DELETE a Friendship, the application needs to have the Friendship "id" available, but in order for the User to know which Friend they are deleting, they need to see the Friend "name".
In other words, is there a RESTful way to request the array of Friend models and their respective array of Friendship models in the same HTTP request?
Below is my current setup:
# Models
class User < ActiveRecord::Base
has_many :friendships, :dependent => :destroy
has_many :friends, :through => :friendships
# disregard inverse for now
end
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => "User"
validates_uniqueness_of :user_id, :scope => :friend_id
end
# Tables
create_table :users do |t|
t.string :name
t.timestamps
end
create_table :friendships do |t|
t.integer :user_id, :null => false
t.integer :friend_id, :null => false
t.integer :status, :null => false, :default => 0
t.timestamps
end
# routes.rb
resources :friendships, :only => [:create, :destroy, :index]
resources :users do
member do
get :friends # index-like action returning array of friends
end
end
... and yes, I have been searching for days :)
I'm working with Rails, but this question stands for any framework. And yes, I know that I have a million ways to "Get 'er done", but I'm looking for the RESTful way of doing this so that I can use any client side framework without having to customize the I/O too much.
Upvotes: 1
Views: 1197
Reputation: 3158
I don't think you would need to issue two separate requests. I think if you were in a position where you only knew the user_id and follower_id, you could implement a finder in your Friendship model to find a friendship based on user_id and friend_id and then delete the one that is found. Though, I think if you wanted to go the pure restful manner, it would be best to pull the friendship.id serverside when you were displaying that frienship relationship. There's a really good example of how to do this in the Rails Tutorial codebase for sample_app. Here, the join model is called relationship, and there is a RelationshipsController with create and destroy actions. The form for handling the destroy action is found in /app/views/users/_unfollow.html.erb and looks like the following:
<%= form_for(current_user.relationships.find_by_followed_id(@user),
:html => { :method => :delete },
:remote => true) do |f| %>
<div class="actions"><%= f.submit "Unfollow" %></div>
<% end %>
Here, the there is a has_many :relationships on the User model and it then uses the find_by_followed_id dynamic finder from ActiveRecord to return the specific relationship object to be deleted. This seems to be the most RESTful way to do it.
Upvotes: 1