Rails 3 friendship model : how to ignore a friend request?
Asked Answered
C

1

1

I have the traditional friendship model:

The user model has:

has_many :friendships, :dependent => :destroy
  has_many :friends, :through => :friendships, :dependent => :destroy
  has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id", :dependent => :destroy
  has_many :inverse_friends, :through => :inverse_friendships, :source => :user, :dependent => :destroy

I would like to define the status "friend" only if a friend request has been sent, and accepted by the other user. Everything works fine except that I did not manage to process the "ignore friend request" part.

What I am trying to do is: on a user profile page, there's a list of requests from other user, waiting approval. The user can then accept a friend request (then it becomes a friend) or reject it (then the friendship relationship is destroyed).

Here is the piece of code, in the friendship controller, when it blocks:

<h2 class="small_v_space">Waiting your approval</h2>
<ul>
  <% for user in @user.inverse_friends %>
    <% if user.friends.exists?(@user) and not @user.friends.exists?(user) %>
      <li>
        <%=h user.name %>
          (<%= link_to "Accept", friendships_path(:friend_id => user), :method => :post %>,
           <%= link_to "Ignore", friendship_path, :controller => :friendships, :method => :delete  %>)
      </li
    <% end %>
  <% end %>
</ul>

The problem is that if I do like this, the delete method will delete the last added relationship, instead of the one linked to the ignore button.

Let's work with an example: Here is the relationship I would like to destroy: User_id: 10 Friend_id: 6 Friendship_id: 18

I'm on the 'show' page (profile) of user, whose user_id is 6. I see that user 10 has made a friend request that I would like to ignore. Even if I managed to extract the proper Friendship_id, doing:

<%= link_to "Ignore", friendship_path(Friendship_id), :controller => :friendships, :method => :delete  %>)

It results in "Cannot find Friendships with ID=18[where user_id=6]"

Does anyone know how I could call the destroy action on the right relationship in this case ? Or should I proceed differently ?

Many thanks for any clue!

EDIT

Destroy action of the friendship controller:

def destroy
    @friendship = current_user.friendships.find(params[:id])
    if @friendship.friend.friends.exists?(current_user)
      @friendship.destroy
      flash[:notice] = "Removed friendship."
    else
      @friendship.destroy
      flash[:notice] = "Removed friend request."
    end
    redirect_to current_user
  end

EDIT 2:

class Friendship
   belongs_to :user
   belongs_to: :friend, :class_name => 'User'
 end

User A sends a friend request to user B (A=user, B=friend in the instance of the class). If B accepts the requests, then another instance is created (B=user, A=friend). If there exists both a relation A->B and B->A, A is a friend of B. Otherwise, the request remains pending (or can be ignored, rejected...).

Crissie answered 20/3, 2012 at 17:58 Comment(5)
I think you're over-complicating things. I'm pretty sure that to do what you want to do, all you'd need would be a friend and friendship model and in the friendship model you'd have an int variable called status or something that would have different values depending on whether the relationship had been accepted or not. But that's beside the point. <%= link_to "Ignore", friendship_path(Friendship_id), :method => :delete %> should work, could you please show the destroy action of your friendships controller?Gubernatorial
@Ashitaka: thanks for the reply! I added the destroy action in the question. You are right, there are other ways to do it, but I feel I could learn much by being able to do it this way. The problem is that being inside the show page of the user_6, even if the right friendship_id is passed, it fails because it says "cannot find Friendship_id=18 WHERE user_id =6 ... I'd like to somehow get rid of this user_id=6 ... I spent hours trying tons of options, I feel a bit confused now :-/ ... thanks anyway !Crissie
Ok, to solve this, we need a little bit more info. Please show your relationship model. And also, how do you distinguish between a user who is your friend and a user who sent you a friend request?Gubernatorial
@Ashitaka: Added the relationship model and answered your question in EDIT2. But I think you were right, I took the wrong path, I think it would be better to work with status field (accepted, ignored, pending) in the friendship model... but still if you see how I should have done the original way, I'd be happy to know ;-)Crissie
See my edited answer! Maybe this time I got it right.Gubernatorial
G
1

I'm editing my whole answer because I think I found the gist of your problem. When a user tries to be friends with someone, you add a relationship to that user but you don't add it to the other user. SO, current_user.friendships.find(params[:id]) expects the current_user to have a friendship with that id but that relationship doesn't belong to him, but to the other user.

I'm not sure if I made it clear enough, but here's my 2nd try:

Your link should be:

<%= link_to "Ignore", friendship_path(:id => friendship_id, :friend_id => user.id), :method => :delete  %>)

And then your action:

def destroy
  potential_friend = User.find(params[:friend_id])
  friend_request = potential_friend.friendships.find(params[:id])

  friendship = current_user.friendships.find_by_friend_id(potential_friend.id)
  if friendship.nil?      #Users are not friends and you want to delete the friend request
    friend_request.destroy
    flash[:notice] = "Removed friend request."
  else                    #Users are friends and you want to delete the friendship
    friendship.destroy
    friend_request.destroy
    flash[:notice] = "Removed friendship."
  end
  redirect_to current_user
end

I'm not sure if you should turn this into custom action. As you can see, it does much more than just destroy a single object.

Gubernatorial answered 21/3, 2012 at 3:41 Comment(2)
Thanks a lot Ashitaka ... indeed, I think I was approaching the problem the wrong way, and your several helping comments was great to receive when you're a bit lost !!... I didn't test the above solution, because I'm gone into another option, with a status[pending, approved, ignored]... Many thanks !!Crissie
I'm glad you changed your mind! That approach is more adequate and simpler to understand so it's easier to implement. Good luck!Gubernatorial

© 2022 - 2024 — McMap. All rights reserved.