前提・実現したいこと
受信したメッセージの横に、未開封であればマークを表示するといった処理をしたいです。
メッセージ機能及び通知機能は既に実装出来ています。
未読・既読機能としては、以下の流れを考えています。
- 通知テーブルに
read
と言うboolean型のカラムを追加する。 /rooms/:id
にアクセスがあった場合にread
の中身をfalse
からtrue
に変える処理を施し、未読かどうかを判定する。true
の場合はマークを表示、/rooms/:id
にアクセスがあった瞬間にマークを消す。
ただコードの記述の仕方が分からず足踏みしています。
「ログイン中のユーザーが抱えるmessage
に関する通知(全件)を取得する」と言った通知機能は記述出来たのですが、「各room
内のmessage
に関する通知をそれぞれ取得する」記述の仕方が分かりません…。
ご助言を頂けますと有難いです。
schema.rb
Ruby
1 create_table "notifications", force: :cascade do |t| 2 t.integer "visitor_id", null: false 3 t.integer "visited_id", null: false 4 t.integer "post_id" 5 t.string "action", default: "", null: false 6 t.boolean "checked", default: false, null: false 7 t.datetime "created_at", null: false 8 t.datetime "updated_at", null: false 9 t.integer "comment_id" 10 t.integer "message_id" 11 t.integer "room_id" 12 t.boolean "read", default: false, null: false #未読・既読判定の為にカラム追加。 13 t.index ["comment_id"], name: "index_notifications_on_comment_id" 14 t.index ["message_id"], name: "index_notifications_on_message_id" 15 t.index ["post_id"], name: "index_notifications_on_post_id" 16 t.index ["room_id"], name: "index_notifications_on_room_id" 17 t.index ["visited_id"], name: "index_notifications_on_visited_id" 18 t.index ["visitor_id"], name: "index_notifications_on_visitor_id" 19 end
messages_controller.rb
Ruby
1 def create 2 @room = @message.room 3 if @message.save! 4 @roommembernotme = Entry.where(room_id: @room.id).where.not(user_id: @current_user.id) 5 @theid = @roommembernotme.find_by(room_id: @room.id) 6 notification = @current_user.active_notifications.new( 7 room_id: @room.id, 8 message_id: @message.id, 9 visited_id: @theid.user_id, 10 visitor_id: @current_user.id, 11 action: 'message' 12 ) 13 if notification.visitor_id == notification.visited_id 14 notification.checked = true 15 notification.read = true # 自分がメッセージを送った場合は既読にする。 16 end 17 notification.save! 18 end
rooms_controller.rb
Ruby
1 def show 2 # ログイン中のユーザーが抱える「message」に関する相手からの通知を取得。 3 @notifications = @current_user.passive_notifications.where(action: 'message').includes([:visitor], [:visited]).order(created_at: :desc).page(params[:page]).per(7) 4 # ログイン中のユーザーが抱える相手からの通知のうち、該当のroom_idを取得し、showを開いた時点でreadをtrueにする。 5 @current_user.passive_notifications.find_by(params[:id]).update(read: true) 6 # 該当のroom_id内にある未読メッセージの数を取得。 7 @unread = @notifications.where(room_id: params[:id], read: false).count 8 end 9 10 def index 11 @rooms = Room.page(params[:page]).per(3) 12 @user = @current_user 13 @currentEntries = @current_user.entries 14 myRoomIds = [] 15 @currentEntries.each do | entry | 16 myRoomIds << entry.room_id 17 end 18 @anotherEntries = Entry.includes(:user, :room).where(room_id: myRoomIds).where('user_id != ?', @user.id).order(created_at: :desc) 19 20 @notifications = @current_user.passive_notifications.where(action: 'message').includes([:visitor], [:visited]).order(created_at: :desc).page(params[:page]).per(7) 21 @notifications.where(checked: false).each do |notification| 22 notification.update_attributes(checked: true) 23 end 24 @unread = @notifications.where(room_id: params[:id], read: false).count 25 end
rooms_index.html.erb
Rails
1 <div class="message-items"> 2 <% @anotherEntries.each do |e| %> 3 <div class="message-item"> 4 <div class="message-left"> 5 <%= link_to room_path(e.room.id) do %> 6 <img src="<%= "/user_images/#{e.user.image_name}" %>"> 7 <% end %> 8 </div> 9 <div class="message-center"> 10 <div class="message-center-username"> 11 <%= link_to room_path(e.room.id) do % 12 <%= e.user.name %> 13 <%= @unread %> 14 <% end %> 15 </div> 16 <div class="message-center-message"> 17 <%= link_to room_path(e.room.id) do %> 18 <% dm = Message.find_by(id: e.room.message_ids.last).try(:content) %> 19 <%= truncate(dm, length: 9) %> 20 <% end %> 21 </div> 22 </div> 23 <div class="message-right"> 24 <div class="message-date" style="color: #C0C0C0;"><%= e.updated_at.strftime("%Y/%m/%d") %></div> 25 <div class="message-time" style="color: #C0C0C0;"><%= e.updated_at.strftime("%H:%M") %></div> 26 </div> 27 </div> 28 <% end %> 29 </div>
補足情報(FW/ツールのバージョンなど)
ruby 2.6.4p104
RubyGems 3.0.3
Rails 5.2.3
【追記】ER図
【追記】解決したコード
rooms_controller.rb
Ruby
1 def index 2 #以下、メッセージ機能に関する記述。変更なし。 3 @rooms = Room.page(params[:page]).per(3) 4 @user = @current_user 5 @currentEntries = @current_user.entries 6 myRoomIds = [] 7 @currentEntries.each do | entry | 8 myRoomIds << entry.room_id 9 end 10 @anotherEntries = Entry.includes(:user, :room).where(room_id: myRoomIds).where('user_id != ?', @user.id).order(created_at: :desc) 11 12 # 既読機能についてはコントローラでは特に記述せず。ビューにて記述。 13 end 14 15 def show 16 #以下、メッセージ機能に関する記述。変更なし。 17 @rooms = Room.page(params[:page]).per(3) 18 @user = @current_user 19 @currentEntries = @current_user.entries 20 myRoomIds = [] 21 @currentEntries.each do | entry | 22 myRoomIds << entry.room_id 23 end 24 @anotherEntries = Entry.includes(:user, :room).where(room_id: myRoomIds).where('user_id != ?', @user.id).order(created_at: :desc) 25 26 # ここから既読機能。ログイン中のユーザーが抱える「message」に関する「相手からの通知」のうち、該当のroom_idを取得し、showを開いた時点でreadをtrueにする。 27 @current_user.passive_notifications.where(action: 'message', read: false, room_id: params[:id]).each do |notification| 28 notification.update_attributes(read: true) 29 end 30 end
rooms_index.html.erb と rooms_show.html.erb(既読機能に関する内容は同じ)
Rails
1 <!-- ログイン中のユーザーが保持している各Entryの中で、未読メッセージがある場合countを繰り返し表示。--> 2 <% message_count = Notification.where(action: "message", visited_id: @current_user.id, visitor_id: e.user.id, room_id: e.room.id, read: false).count %> 3 <% if message_count > 0 %> 4 <div class="message-count date-and-count"><%= message_count %></div> 5 <% end %>
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/20 03:41