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