Add notification to RoR messaging inbox system

痞子三分冷 提交于 2021-01-28 19:08:14

问题


I have a rails app with intern messaging system. User can send message to other user. Example : User 1 send message User 2 can respond viceversa.

All works perfectly. But I want to upgrade this system with notfications functionnality. I want to type of notifications :

1) On navbar 2) By mail

Problem : I dont know how i can do this.

Can you help me ?

Conversations table

class CreateConversations < ActiveRecord::Migration
 def change
  create_table :conversations do |t|
   t.integer :sender_id
   t.integer :recipient_id
   t.timestamps
  end
 end
end

Messages table. In this code I have a boolean :read. I think solution can be here. What do you think about this ?

class CreateMessages < ActiveRecord::Migration
 def change
  create_table :messages do |t|
   t.text :body
   t.references :conversation, index: true
   t.references :user, index: true
   t.boolean :read, :default => false
   t.timestamps
  end
 end
end

conversation.rb

class Conversation < ActiveRecord::Base
 belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
 belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User'
has_many :messages, dependent: :destroy
validates_uniqueness_of :sender_id, :scope => :recipient_id
scope :between, -> (sender_id,recipient_id) do
 where("(conversations.sender_id = ? AND conversations.recipient_id =?) OR (conversations.sender_id = ? AND conversations.recipient_id =?)", sender_id,recipient_id, recipient_id, sender_id)
 end
end

Message.rb

class Message < ActiveRecord::Base
 belongs_to :conversation
 belongs_to :user
 validates_presence_of :body, :conversation_id, :user_id
 def message_time
  created_at.strftime("%m/%d/%y at %l:%M %p")
 end
end

conversations_controller.rb

class ConversationsController < ApplicationController
  before_action :authenticate_user!

  # GET /conversations
  # GET /conversations.json
  def index
    @users = User.all

    # Restrict to conversations with at least one message and sort by last updated
    @conversations = Conversation.joins(:messages).uniq.order('updated_at DESC')
  end

  # POST /conversations
  # POST /conversations.json
  def create
  if Conversation.between(params[:conversation][:sender_id], params[:conversation][:recipient_id]).present?
    @conversation = Conversation.between(params[:conversation][:sender_id], params[:conversation][:recipient_id]).first
  else
    @conversation = Conversation.create!(conversation_params)
  end

  redirect_to conversation_messages_path(@conversation)
end

  private
    # Use callbacks to share common setup or constraints between actions.
    def conversation_params
      params.require(:conversation).permit(:sender_id, :recipient_id)
    end
end

messages_controller.rb

class MessagesController < ApplicationController
  before_action do
   @conversation = Conversation.find(params[:conversation_id])
  end
def index
 @messages = @conversation.messages
  if @messages.length > 10
   @over_ten = true
   @messages = @messages[-10..-1]
  end
  if params[:m]
   @over_ten = false
   @messages = @conversation.messages
  end
 if @messages.last
  if @messages.last.user_id != current_user.id
   @messages.last.read = true;
  end
 end
@message = @conversation.messages.new
 end
def new
 @message = @conversation.messages.new
end
def create
 @message = @conversation.messages.new(message_params)
 if @message.save
  redirect_to conversation_messages_path(@conversation)
 end
end
private
 def message_params
  params.require(:message).permit(:body, :user_id)
 end
end

/conversations/index.html.erb

<div class="ui segment">
 <h3>Mailbox</h3>
 <div class="ui list">
  <div class="item">
   <% @conversations.each do |conversation| %>
   <% if conversation.sender_id == current_user.id || conversation.recipient_id == current_user.id %>
    <% if conversation.sender_id == current_user.id %>
      <% recipient = User.find(conversation.recipient_id) %>
    <% else %>
      <% recipient = User.find(conversation.sender_id) %>
    <% end %>
    Conversation avec <%= link_to recipient.prenom,   conversation_messages_path(conversation)%>
   <% end %>
  <% end %>
  </div>
 </div>
</div>
<div class="ui segment">
 <h3>All Users</h3>
  <div class="ui list">
   <% @users.each do |user| %>
    <% if user.id != current_user.id %>
     <div class="item">
   <%= user.prenom %> <%= button_to 'Message me', conversations_path(conversation: { sender_id: current_user.id, recipient_id: user.id }), class: 'btn btn-primary m-t' %>
 </div>
  <% end %>
 <% end %>
 </div>
</div>

messages/index.html.erb

<% if @over_ten %>
 <%= link_to 'Show Previous', "?m=all" %>
<% end %>
<div class="ui segment">
 <% @messages.each do |message| %>
  <% if message.body %>
   <% user = User.find(message.user_id) %>
   <div class="item">
    <div class="content">
     <div class="header"><strong><div class="imageavatarmessage"><%= image_tag user.avatar(:thumb), class:"imageavatarmessage" %></div><%= user.prenom %></strong>     <%= message.message_time %></div>
      <div class="list">
       <div class="item">
        <i class="right triangle icon"></i>
         <%= message.body %>
      </div>
    </div>
   </div>
 </div>
 <% end %>
<% end %>
</div>
<%= form_for [@conversation, @message], html: {class: "ui reply form"} do |f| %>
 <div class=”field”>
   <%= f.text_area :body, class: "form-control" %>
 </div>
 <%= f.text_field :user_id, value: current_user.id, type: "hidden" %>
 <div>
   <%= f.submit "Add Reply", class: "ui blue labeled submit icon button" %>
 </div>
<% end %>

回答1:


I would recommend you to go through this tutorial to build nice notification system https://www.devwalks.com/lets-build-instagram-part-6-notifications/

Basically, you have to create new model, set dependencies with your Message model and integrate to the controller

For the email notifications, it's even simpler. Just create new mailer and fire it on create action in messages_controller

def create
 @message = @conversation.messages.new(message_params)
 if @message.save
  SendMessageMailer.new_message(@message).deliver_later
  redirect_to conversation_messages_path(@conversation)
 end
end

EDIT: To create mailer, you should do something like this:

rails g mailer SendMessage

Go to /app/mailers/send_message_mailer.rb and add action, same type of building as controllers

def new_message(message)
    @message = message
    mail(to: @message.user.email, subject: 'Hey! Here is what you missed')
end

Also, create an view (email template) and code with erb code

app/views/send_message_mailer/new_message.html.erb

Im not going deep into this, I guess you can figure out how to pass interval (let's say don't send if user is online or have read the message) and differentiate with receiver/sender users

Mailer, once again, is just same type of controller. You can pass as many params as you need and use model nesting inside mailer controller and views

mailer

def new_message(message, sender, receiver)
end

controller

SendMessageMailer.new_message(@message, @message.user, params[:receiver]).deliver_later


来源:https://stackoverflow.com/questions/40431718/add-notification-to-ror-messaging-inbox-system

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!