I have user model and I am using has_and_belongs_to_many
on Rails to make a relation between user and friend model.
User can has many friends and friend can has many friends. I need to get all friends of specific user, how can I do that?
In user.rb file:
has_and_belongs_to_many :friendships, class_name: "User", join_table: :friendships,
foreign_key: :user_id,
association_foreign_key: :friend_user_id}
In 20180309142447_create_friendships_table.rb file:
class CreateFriendshipsTable < ActiveRecord::Migration[5.1]
def change
create_table :friendships, id: false do |t|
t.integer :user_id
t.integer :friend_user_id
end
add_index(:friendships, [:user_id, :friend_user_id], :unique => true)
add_index(:friendships, [:friend_user_id, :user_id], :unique => true)
end
end
I need to get all friends of specific user, how can I do that ?
Implementing a friendship between two users
I assume you are willing to implement a friendship pattern like Facebook:
For this we need a friendship model which replaces your has_many_and_belongs_to
-built in function. The friendship models will help us to identify active and pending friendship requests between users. The friendship model only has a user (initiator) and a friend (whom the user sent the request).
Scenario:
active_friends
and pending_friends
you can get the data for your views or API# new migration
# $ rails g migration create_friendships
def change
create_table :friendships do |t|
t.integer :user_id
t.integer :friend_id
t.timestamps null: false
end
end
create a new friendship model
# friendship.rb
class Friendship < ActiveRecord::Base
# - RELATIONS
belongs_to :user
belongs_to :friend, class_name: 'User'
# - VALIDATIONS
validates_presence_of :user_id, :friend_id
validate :user_is_not_equal_friend
validates_uniqueness_of :user_id, scope: [:friend_id]
def is_mutual
self.friend.friends.include?(self.user)
end
private
def user_is_not_equal_friend
errors.add(:friend, "can't be the same as the user") if self.user == self.friend
end
end
in your User model you can handle the friendships rails-like
# user.rb
has_many :friendships, dependent: :destroy
has_many :friends, through: :friendships
to get the friendships someoneelse sent to "you"
has_many :received_friendships, class_name: 'Friendship', foreign_key: 'friend_id'
has_many :received_friends, through: :received_friendships, source: 'user'
def active_friends
friends.select{ |friend| friend.friends.include?(self) }
end
def pending_friends
friends.select{ |friend| !friend.friends.include?(self) }
end