24
loading...
This website collects cookies to deliver better user experience
sender
and a receiver
, both belonging to the User class. Similarly, a Friendship object is initiated with a sender
and a receiver
. If a user has many friend requests on their notifications page, it is necessary to determine which specific friend request is being accepted or declined when the receiver clicks "Accept" or "Decline", respectively.notification.sender
andnotification.receiver
. The "Accept" button is as follows:<% friendship = Friendship.find_by(sender_id: notification.sender.id,
receiver_id: notification.receiver.id) %>
<%= button_to "Accept",
friendship_path(friendship),
method: :put,
params: { friendship: { status: 'accepted' } } %>
sender_id
. The current user will always be the receiver in this situation and to find the Friendship request sent to the current user, we only need the sender_id
. I thought it made sense to make this method an instance method on User but there are probably better ways to do this. Let me know in the comments! Here are the relevant models and associations.class User < ApplicationRecord
has_many :sent_notifications,
class_name: 'Notification',
foreign_key: 'sender_id',
dependent: :destroy
has_many :received_notifications,
class_name: 'Notification',
foreign_key: 'receiver_id',
dependent: :destroy
has_many :sent_pending_requests, -> { friendship_pending },
class_name: 'Friendship',
foreign_key: 'sender_id',
dependent: :destroy
has_many :received_pending_requests, -> { friendship_pending },
class_name: 'Friendship',
foreign_key: 'receiver_id',
dependent: :destroy
# ...
end
class Notification < ApplicationRecord
belongs_to :sender, class_name: 'User'
belongs_to :receiver, class_name: 'User'
#...
end
class Friendship < ApplicationRecord
enum status: %i[pending accepted declined]
belongs_to :sender, class_name: 'User'
belongs_to :receiver, class_name: 'User'
scope :friendship_pending, -> { where(status: :pending) }
#...
end
class User
#...associations, etc.
def requests_via_sender_id
requests = received_pending_requests
sender_ids = requests.pluck(:sender_id)
sender_ids.to_h do |id|
[id, requests.find_by(sender_id: id)]
end
end
end
received_pending_requests.count == 1
at the moment. A user with an id of 3 has sent current_user
a request.current_user.requests_via_sender_id =>
{3=>
#<Friendship:0x000055f71022ec20
id: 16,
status: "pending",
sender_id: 3,
receiver_id: 1 }
class NotificationsController < ApplicationController
def index
@notifications = current_user.received_notifications.includes(%i[sender receiver])
@friendships = current_user.requests_via_sender_id # => returns a hash
end
end
friendship
local variable:<%= button_to "Accept",
friendship_path(@friendships[notification.sender.id]),
method: :put,
params: { friendship: { status: 'accepted' } }%>
friendship_path(@friendships[notification.sender.id])
. This is arguably more expressive than friendship_path(friendship)
, because it provides the context in which we are searching for a Friendship object.