Reputation: 2914
I have a custom inbox messaging system and I would like to fix the delete function of messages. At the moment when User A deletes a message, it will not permanently be deleted from database until User B also deletes the message. So the message will remain in the users Inbox/Delete folder until both the sender and recipient has erased the message.
How I would like it to function is that if one user deletes the message from their inbox or clicks the delete button again for messages inside their delete folder...the message should remain hidden as if it were deleted. Thus making that message non-viewable to the User who selected to delete it. Then of course with how I have it setup already, the message will be permanently deleted from database if both users have selected to delete it.
When message is soft deleted (hidden from one user until it is permanently deleted from database), it should not be viewable by that user. If they're browsing their messages and are using the next/previous links...messages that they've deleted should not appear while clicking next/previous.
Any help would be appreciated!
messages controller:
def index
if params[:mailbox] == "sent"
@messages = @user.sent_messages
elsif params[:mailbox] == "inbox"
@messages = @user.received_messages
#elsif params[:mailbox] == "archieved"
# @messages = @user.archived_messages
end
if params[:mailbox] == "unread"
@messages = @user.unread_messages
end
end
def new
@message = Message.new
if params[:reply_to]
@reply_to = User.find_by_user_id(params[:reply_to])
unless @reply_to.nil?
@message.recipient_id = @reply_to.user_id
end
end
end
def create
@message = Message.new(params[:message])
@message.sender_id = @user.id
if @message.save
flash[:notice] = "Message has been sent"
redirect_to user_messages_path(current_user, :mailbox=>:inbox)
else
render :action => :new
end
end
def show
@message = Message.find(params[:id])
@message.readingmessage if @message.recipient == current_user
end
def destroy
@message = Message.find(params[:id])
@message.destroy
flash[:notice] = "Successfully deleted message."
redirect_to user_messages_path(@user, @messages)
end
def delete_multiple
if params[:delete]
params[:delete].each { |id|
@message = Message.find(id)
@message.mark_message_deleted(@message.id,@user.id) unless @message.nil?
}
flash[:notice] = "Messages deleted"
end
redirect_to user_messages_path(@user, @messages)
end
private
def set_user
@user = current_user
end
end
messages model:
belongs_to :sender,
:class_name => 'User',
:foreign_key => 'sender_id'
belongs_to :recipient,
:class_name => 'User',
:foreign_key => 'recipient_id'
# marks a message as deleted by either the sender or the recipient, which ever the user that was passed is.
# When both sender and recipient marks it deleted, it is destroyed.
def mark_message_deleted(id,user_id)
self.sender_deleted = true if self.sender_id == user_id
self.recipient_deleted = true if self.recipient_id == user_id
(self.sender_deleted && self.recipient_deleted) ? self.destroy : self.save!
end
# Read message and if it is read by recipient then mark it is read
def readingmessage
self.read_at ||= Time.now
save
end
# Based on if a message has been read by it's recipient returns true or false.
def read?
self.read_at.nil? ? false : true
end
def self.received_by(user)
where(:recipient_id => user.id)
end
def self.not_recipient_deleted
where("recipient_deleted = ?", false)
end
def self.sent_by(user)
Message.where(:sender_id => user.id)
end
def previous(same_recipient = true)
collection = Message.where('id <> ? AND created_at > ?', self.id, self.created_at).order('created_at ASC')
collection.where(recipient_id: self.recipient_id) if same_recipient
collection.first
end
def next(same_recipient = true)
collection = Message.where('id <> ? AND created_at < ?', self.id, self.created_at).order('created_at DESC')
collection.where(recipient_id: self.recipient_id) if same_recipient
collection.first
end
end
inbox view:
<%= form_tag delete_multiple_user_messages_path, :method=>:post do %>
<table class="table table-bordered">
<tr>
<th>Delete</th>
<th>Subject</th>
<th>Date</th>
<th>From</th>
</tr>
<% for message in @messages %>
<tr>
<td><%= check_box_tag "delete[]", message.id %></td><p>
<td>
<% if message.read? %>
<%= link_to h(message.subject), user_message_path(@user, message) %>
<% else %>
<%= link_to "#{h(message.subject)} (unread)", user_message_path(@user, message) %>
<% end %>
</td>
<td><%=h message.created_at.to_s(:long) %></td>
<td><%= "#{message.sender}" %></td>
</tr>
<% end %>
</table>
<%= submit_tag "Delete selected" %>
Upvotes: 1
Views: 336
Reputation: 76
I see this method in your model, but I don't see you calling it anywhere:
def self.not_recipient_deleted
where("recipient_deleted = ?", false)
end
I believe if you change this for loop in the inbox view
<% for message in @messages %>
to
<% for message in @messages.not_recipient_deleted %>
it will return only the messages that the recipient hasn't deleted. That should keep the deleted messages from being displayed in the inbox.
Upvotes: 1
Reputation: 3083
you can use this in controller for index action @messages = @user.received_messages.where(recipient_deleted: false)
so it will load only messages that are not deleted by the recipient
Upvotes: 0