Reputation: 11206
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
Reputation: 21557
I suggest you add the unit tests for those associations, since they look like complicated and not easy to understand.
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
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