Huy
Huy

Reputation: 11206

View not hiding 'Add Friend' link during a pending friend request (friendship relationship model)

I am trying to hide my "Add friend" link if
- current_user and @user are friends
- there is a pending friend request
- current_user and @user have the same id (same user)

The "Add friend" link does not show if current_user and @user are friends. The problem is when there is a pending friend request. I still see the "Add friend" link after I submit a friend request.

Is there something wrong with the conditions in my view?

When I run these two conditions in my console: current_user.pending_friends.include?(@user) and @user.pending_friends.include?(current_user), I get a false even though my database shows a pending request.

Here is my view:

users/show.html.erb

<% if signed_in? %>
  <% if @user == current_user || current_user.friends.include?(@user) 
        || current_user.pending_friends.include?(@user) 
        || @user.pending_friends.include?(current_user)  %>


   <% else %>      

    <%= link_to  friendships_path(:user_id => current_user.id, 
            :friend_id => @user.id), :method => :post, :action => 'create' do %>

    Add Friend

    <% end %>
  <% end %>
<% end %>

User Model

has_many :friendships

has_many :inverse_friendships, 
 :class_name => "Friendship", 
 :foreign_key => "friend_id"

has_many :direct_friends, 
 :through => :friendships, 
 :conditions => "status = 'accepted'", 
 :source => :friend

has_many :inverse_friends, 
 :through => :inverse_friendships, 
 :conditions => "status = 'accepted'", 
 :source => :user

has_many :pending_friends, 
 :through => :friendships, 
 :conditions => "status = 'pending'", 
 :foreign_key => "user_id", 
 :source => :user   #this line is incorrect. see correction below.

has_many :requested_friends, 
 :through => :friendships,
 :source => :friend, 
 :conditions => "status = 'requested'"

def friends
  direct_friends | inverse_friends
end

Here is the create action from my friendships controller so you guys can see how the relationship is being created in the db:

def create
  @user = User.find(current_user)
  @friend = User.find(params[:friend_id])
  params[:friendship1] = {:user_id => @user.id, :friend_id => @friend.id, :status => 'pending'}
  params[:friendship2] = {:user_id => @friend.id, :friend_id =>@user.id, :status => 'requested'}
  @friendship1 = Friendship.create(params[:friendship1])
  @friendship2 = Friendship.create(params[:friendship2])

  if @friendship1.save && @friendship2.save
    flash[:success] = "Friend request submitted."
    redirect_to @friend
  else 
    flash[:error] = "Friend request failed."
    redirect_to @friend
  end  
end

Thanks for looking!

Edit: Found my mistake and posted the answer below.

The source for :pending_friends should be :friend, not :user. Correction below.

has_many :pending_friends, 
:through => :friendships, 
:conditions => "status = 'pending'", 
:foreign_key => "user_id", 
:source => :friend

Upvotes: 0

Views: 556

Answers (1)

Siwei
Siwei

Reputation: 21557

I suggest you add the unit tests for those associations, since they look like complicated and not easy to understand.

  1. add fixtures:

    # test/fixtures/users.yml
    current_user: 
      id: 1
      name: Current User
    another_user:
      id: 2 
      name: Your friend
    
    # test/fixtures/friendships.yml
    pending_friend:
      id: 1
      status: pending
      user_id: 1 # 
      # other attributes
    requested_friend:
      id: 2
      status: requested
      user_id: 2 # 
      # other attributes
    
  2. write the unit test code to tell yourself that the associations are correct:

    # test/model/user_test.rb
    class UserTest <  # extend Rails unit test class
      def test_the_requested_friendship 
        assert users(:current_user).requested_friends.include?( users(:another_user))
      end
      def test_the_pending_friendships
        # your assertion here
      end
    end
    

NOTICE: the code above is just an idea, I haven't make them tested yet. you should implement your code yourself.

and I suggest that you use "rspec" since it's more expressive than the classic test-unit.

Upvotes: 1

Related Questions