Reputation: 119
I'm creating a RoR mock facebook where Users can add each other as friends. I'm having trouble accessing the friend relationship from one side of the friendship. For example, I have user 'Ben' who adds user 'Jordan'. This action goes through the friendships controller below
def create
@friendship = current_user.friendships.build(friend_id: params[:friend_id], confirmed: false)
if @friendship.save
flash[:notice] = "Friend Request Sent."
redirect_to root_url
else
flash[:notice] = "Unable to send friend request."
redirect_to root_url
end
end
The User Model below has methods to help me access information about each user.
In rails console after I had accepted the friend request, I search for each users friends. After designating ben
to be the ben user object, and jordan
to be the jordan user object in the rails console I look up ben.friends_list
and ben.friends
and jordan shows up for both. But when I look up jordan.friends_list
and jordan.friends
I get a blank array and blank Active Record Association.
When I look up the friendship that exists between them that was created when Ben added Jordan it says it exists between them both. (Ben's ID = 4 and Jordans ID = 3) #<Friendship id: 1, user_id: 4, friend_id: 3, confirmed: true, created_at: "2020-07-25 19:12:06", updated_at: "2020-07-25 19:24:26">
I think the problem may be in my associations, or in the model methods for my User. Any help would be appreciated.
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :friendships, dependent: :destroy
has_many :friends, through: :friendships
has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id"
has_many :inverse_friends, through: :inverse_friendships, source: :user
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
def friends_list
friends_array = friendships.map{|friendship| friendship.friend if friendship.confirmed}
friends_array + inverse_friendships.map{|friendship| friendship.user if friendship.confirmed}
friends_array.compact
end
#users who haven't accepted friend request
def pending_friends
friendships.map{|friendship| friendship.friend if !friendship.confirmed}.compact
end
#users who have requested to be friends
def friend_requests
inverse_friendships.map{|friendship| friendship.user if !friendship.confirmed}.compact
end
def confirm_friend(user)
friendship = inverse_friendships.find{|friendship| friendship.user == user}
friendship.confirmed = true
friendship.save
end
def friend?(user)
friends_list.include?(user)
end
end
Upvotes: 0
Views: 547
Reputation: 84
Hello hope that my answers help you
I personally recommend you to use query-based since it's way much faster and efficient than using Ruby own methods: So for example in order to get Friendship request you can use a scope(model method)
has_many :friendships_requests, lambda { |user| unscope(where: :user_id) .where("status = 'Pending'") .where('friendships.user_id = :user_id OR friendships.other_user_id = :user_id ', user_id: user.id) }, class_name: 'Friendship'
This scope will give you whether the user_id(sender) or other_user_id(receiver) status is pending. So in order to get friends you will apply the same methodology but with the difference that the status is now active it will go something like this:
has_many :friends, lambda { |user|unscope(where: :user_id).where("status = 'Active'") .where('friendships.user_id = :user_id OR friendships.other_user_id = :user_id ',user_id: user.id)},class_name: 'Friendship'
both queries are the same but the main difference is the status
Upvotes: 1