rueeazy
rueeazy

Reputation: 119

Rails _ Friends of Users Relationships

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

Answers (1)

Fernando rivas
Fernando rivas

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

Related Questions