Let's make it with reference to this article!
ruby
rails g model Notification visitor_id:integer visited_id:integer room_id:integer message_id:integer action:string checked:boolean
Association between User model and Notification model
app/models/user.rb
has_many :active_notifications, class_name: 'Notification', foreign_key: 'visitor_id', dependent: :destroy
has_many :passive_notifications, class_name: 'Notification', foreign_key: 'visited_id', dependent: :destroy
Association of Room model and Notification model
app/models/room.rb
has_many :notifications, dependent: :destroy
Association of Message model and Notification model
app/models/message.rb
has_many :notifications, dependent: :destroy
Association of Notification model with User, Room, Message model
app/models/notification.rb
  default_scope -> { order(created_at: :desc) }
  belongs_to :room, optional: true
  belongs_to :message, optional: true
  belongs_to :visitor, class_name: 'User', foreign_key: 'visitor_id', optional: true
  belongs_to :visited, class_name: 'User', foreign_key: 'visited_id', optional: true
messages_controller.rb
class MessagesController < ApplicationController
    def create
        if Entry.where(user_id: current_user.id, room_id: params[:message][:room_id]).present?
          @message = Message.new(message_params)
          #from here
          @[email protected]
          #Add up to here
          if @message.save
            #from here
            @roommembernotme=Entry.where(room_id: @room.id).where.not(user_id: current_user.id)
            @[email protected]_by(room_id: @room.id)
            notification = current_user.active_notifications.new(
                room_id: @room.id,
                message_id: @message.id,
                visited_id: @theid.user_id,
                visitor_id: current_user.id,
                action: 'dm'
            )
            #If it is a comment for your post, it will be notified
            if notification.visitor_id == notification.visited_id
                notification.checked = true
            end
            notification.save if notification.valid?
            #Add up to here
            redirect_to "/rooms/#{@message.room_id}"
          end
        else
          redirect_back(fallback_location: root_path)
        end
    end
  
    private 
      def message_params
          params.require(:message).permit(:user_id, :body, :room_id).merge(user_id: current_user.id)
      end
end
terminal
rails g controller notifications index
controller/notifications_controller.rb
class NotificationsController < ApplicationController
  def index
    @notifications = current_user.passive_notifications
  end
end
erb:views/notifications/index.html.erb
<% notifications = @notifications.where.not(visitor_id: current_user.id) %>
<% if notifications.exists? %>
    <%= render notifications %>
<% else %>
    <p>There is no notification</p>
<% end %>
erb:views/notifications/_notificastion.html.erb
<% visitor = notification.visitor %>
<% visited = notification.visited %>
<div>
 <%= link_to user_path(visitor) do %>
     <%= visitor.name %>Is
 <% end %>
 <% if notification.action=='dm' %>
I sent you a DM
 <% end %>
</div>

1: Judge whether it is a message sent by the other party from the message sent by yourself 2: Apply different CSS to the message sent by yourself and the message sent by the other party
It seems that it can be implemented in these 2 steps! The point is step 1.
How do you judge? That's it. There should have been a user_id column in the Message table that makes up the message function. (Pre-existed to determine who posted it) From the value entered there, it seems that you can judge whether it is a message sent by the other party from the message sent by yourself! So let's try it out in the next chapter!
erb:rooms/show.html.erb
<% @messages.each do |m| %> <%#Please change the instance variables here to your own instance variables!%>
    <% if m.user_id == current_user.id %>
        <div class="current_user">
            <strong class="current_user"><%= m.body %></strong>
            <small class="current_user"><%= m.user.name %>Mr.</small>
        </div>
    <% else %>
        <div class="visited_user">
            <strong class="visited_user"><%= m.body %></strong>
            <small class="visited_user"><%= m.user.name %>Mr.</small>
        </div>
    <% end %>
<% end %>
Do you know what you're doing above? !! If the value of user_id is the id of the logged-in user, put the class current_user in the message box (div). If the value of user_id is the id of the other user (strictly speaking, the id is other than the logged-in user), put the class visited_user in the message box (div). We have given it!
CSS example)
css
.current_user {
    color: red;
    text-align: right;
    background-color: #fff;
    width: fit-content;
    margin: 10px 0 0 auto;
    border-radius: 30px;
    -webkit-border-radius: 30px;
    -moz-border-radius: 30px;
    -ms-border-radius: 30px;
    -o-border-radius: 30px;
    box-sizing: border-box;
    padding: 10px;
}
.visited_user {
    color: #fff;
    margin: 10px;
    background-color: brown;
    text-align: left;
    width: fit-content;
    margin: 10px auto 0 0;
    border-radius:30px;
    -webkit-border-radius:30px;
    -moz-border-radius:30px;
    -ms-border-radius:30px;
    -o-border-radius:30px;
    box-sizing: border-box;
    padding: 10px;
}
Assumption: Notification function is implemented in Notification model The columns include id, visitor_id, visited_id, room_id, message_id, action, checked, created_at, updated_at Scheduled to manage read and unread in checked column (boolean type)
1: Show only unread notifications (ie, only show if checked column is false) 2: Initially, unread by default 3: If you press the "Mark as read" link, you can set the checked column to true to make it read.
If you follow the above steps, you can implement it!
erb:_notification.html.erb
<% if notification.checked == false %> <%#← This one line is important%>
    <div>
        <%= link_to room_path(@roomId) do %>
            <%= visitor.name %>Mr.
        <% end %>
        <% if notification.action=='dm' %>
Is you(<%= visited.name %>Mr.)Sent DM to
        <% end %>
        <%= link_to 'Mark as read',notification_path(notification.id),method: :put %>
    </div>
<% end %> <%#← This one line is important%>
Since the checked column is set to false in the first place, do not change it!
rb:_notification.html.erb
class NotificationsController < ApplicationController
  def index
    @notifications = current_user.passive_notifications
    #↓ If you have something written below this, especially if you are writing a process that makes check true, delete that description!
  end
end
erb:_notification.html.erb
<% if notification.checked == false %>
    <div>
        <%= link_to room_path(@roomId) do %>
            <%= visitor.name %>Mr.
        <% end %>
        <% if notification.action=='dm' %>
Is you(<%= visited.name %>Mr.)Sent DM to
        <% end %>
        <%= link_to 'Mark as read',notification_path(notification.id),method: :put %>
        <%#↑ This one line! !!%>
    </div>
<% end %>
Call the update action of the notification controller when you press "Mark as read". At that time, the id of the Notification table is used as an argument as a parameter.
notification_controller
class NotificationsController < ApplicationController
  #abridgement
  def update
    notification=Notification.find(params[:id]) #...①
    if notification.update(checked: true) #...②
      redirect_to action: :index
    end
  end
end
Then, according to (1), the record with the corresponding id in the Notification table is pulled out below the id passed as the parameter. Finally, by ②, set the value of the checked column of the record to true.
You should now be able to implement it! !! !!
[Rails] Explain so that anyone can implement the notification function [Like, comment, follow]
Recommended Posts