站内信

1.创建model

rails g model notification

添加 migration

class CreateNotifications < ActiveRecord::Migration[5.0]
  def change
    create_table :notifications do |t|
      t.integer :recipient_id
      t.integer :actor_id
      t.datetime :read_at
      t.string :action
      t.integer :notifiable_id
      t.string :notifiable_type

      t.timestamps
    end
  end
end

rake db:migrate

补充model

class Notification < ApplicationRecord
   belongs_to :recipient, class_name: "User"
   belongs_to :actor, class_name: "User"
   belongs_to :notifiable, polymorphic: true

   scope :unread, -> { where(read_at: nil) }
   scope :recent, -> { order(created_at: :desc).limit(5) }
 end

2.创建controller

rails g controller notifications



class NotificationsController < ApplicationController  
  before_action :authenticate_user!
  def index
    @notifications = Notification.where(recipient: current_user).recent
  end

  def mark_as_read
    @notifications = Notification.where(recipient: current_user).unread
    @notifications.update_all(read_at: Time.zone.now)
    render json: { success: true }
  end
end

3.在notifications.coffee中加入

class Notifications

  constructor: ->

@notifications = $("[data-behavior='notifications']")

if @notifications.length > 0
  @handleSuccess @notifications.data("notifications")
  $("[data-behavior='notifications-link']").on "click", @handleClick

  setInterval (=>
    @getNewNotifications()
  ), 5000

  getNewNotifications: ->
$.ajax(
  url: "/notifications.json"
  dataType: "JSON"
  method: "GET"
  success: @handleSuccess
)

handleClick: (e) =>
$.ajax(
  url: "/notifications/mark_as_read"
  dataType: "JSON"
  method: "POST"
  success: ->
    $("[data-behavior='unread-count']").text(0)
)

handleSuccess: (data) =>
  items = $.map data, (notification) ->
    notification.template

  unread_count = 0
  $.each data, (i, notification) ->
    if notification.unread
      unread_count += 1

  if unread_count > 0
    $("[data-behavior='unread-count']").html("<span class='label label-danger'>" + unread_count + "</span>")
  else
    $("[data-behavior='unread-count']").text(unread_count)
  $("[data-behavior='notification-items']").html(items)

jQuery ->

  new Notifications

4.在notifications.scss中加入

.unread {
 border-left: 3px solid red;
}

5.创建notification_service.rb

NotificationService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class NotificationService
# recipient 接收者
# actor 发起者
# notifiable 哪张表发起的 比如,question要提醒用户,这里就传question
def initialize(recipient, actor, notifiable)
@recipient = recipient
@actor = actor
@notifiable = notifiable
end
# 发送信息
def send_notification!
Notification.create(recipient: @recipient, actor: @actor, action: "notify_message", notifiable: @notifiable)
end
end

6.创建app/views/notifications/questions/_notify_message.html.erb
如果需要另外一个model也发送
创建app/views/notifications/answers/_notify_message.html.erb

比如,app/views/notifications/questions/_notify_message.html.erb,这里展示消息要呈现的内容

1
2
3
4
5
6
7
<div class="panel-body">
<%= notification.actor.name %> 邀请您回答他的问题
<%= link_to("去回答",new_question_answer_path(notification.notifiable_id)) %>
</div>

_notify_message.html.erb 的名字需要和
需要和action: “notify_message”一致,看一下notifications的表结构中有action的字段

questions的目录和要发送的model一致

7.在需要发送消息的地方调用service

1
2
3
#将会把@question的id和model('Question')的名字存入notifications的#notifiable_id和notifiable_type
NotificationService.new(user,current_user,@question).send_notification!

或者

# 将会把@answer的id和model的名字('Answer')存入notifications的
# notifiable_id和notifiable_type
NotificationService.new(@question.user,current_user,@answer).send_notification!