Adding unified streamable notifications
This commit is contained in:
		@@ -10,7 +10,7 @@ module ApplicationCable
 | 
				
			|||||||
      return [nil, message] if message['type'] == 'delete'
 | 
					      return [nil, message] if message['type'] == 'delete'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      status             = Status.find_by(id: message['id'])
 | 
					      status             = Status.find_by(id: message['id'])
 | 
				
			||||||
      message['message'] = FeedManager.instance.inline_render(current_user.account, status)
 | 
					      message['message'] = FeedManager.instance.inline_render(current_user.account, 'api/v1/statuses/show', status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      [status, message]
 | 
					      [status, message]
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								app/controllers/api/v1/notifications_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/controllers/api/v1/notifications_controller.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Api::V1::NotificationsController < ApiController
 | 
				
			||||||
 | 
					  before_action -> { doorkeeper_authorize! :read }
 | 
				
			||||||
 | 
					  before_action :require_user!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  respond_to :json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def index
 | 
				
			||||||
 | 
					    @notifications = Notification.where(account: current_account).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    next_path = api_v1_notifications_url(max_id: @notifications.last.id)    if @notifications.size == 20
 | 
				
			||||||
 | 
					    prev_path = api_v1_notifications_url(since_id: @notifications.first.id) unless @notifications.empty?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set_pagination_headers(next_path, prev_path)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -26,7 +26,7 @@ class FeedManager
 | 
				
			|||||||
  def push(timeline_type, account, status)
 | 
					  def push(timeline_type, account, status)
 | 
				
			||||||
    redis.zadd(key(timeline_type, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
 | 
					    redis.zadd(key(timeline_type, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
 | 
				
			||||||
    trim(timeline_type, account.id)
 | 
					    trim(timeline_type, account.id)
 | 
				
			||||||
    broadcast(account.id, type: 'update', timeline: timeline_type, message: inline_render(account, status))
 | 
					    broadcast(account.id, type: 'update', timeline: timeline_type, message: inline_render(account, 'api/v1/statuses/show', status))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def broadcast(timeline_id, options = {})
 | 
					  def broadcast(timeline_id, options = {})
 | 
				
			||||||
@@ -39,7 +39,7 @@ class FeedManager
 | 
				
			|||||||
    redis.zremrangebyscore(key(type, account_id), '-inf', "(#{last.last}")
 | 
					    redis.zremrangebyscore(key(type, account_id), '-inf', "(#{last.last}")
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def inline_render(target_account, status)
 | 
					  def inline_render(target_account, template, object)
 | 
				
			||||||
    rabl_scope = Class.new do
 | 
					    rabl_scope = Class.new do
 | 
				
			||||||
      include RoutingHelper
 | 
					      include RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,7 +56,7 @@ class FeedManager
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Rabl::Renderer.new('api/v1/statuses/show', status, view_path: 'app/views', format: :json, scope: rabl_scope.new(target_account)).render
 | 
					    Rabl::Renderer.new(template, object, view_path: 'app/views', format: :json, scope: rabl_scope.new(target_account)).render
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,46 +3,38 @@
 | 
				
			|||||||
class NotificationMailer < ApplicationMailer
 | 
					class NotificationMailer < ApplicationMailer
 | 
				
			||||||
  helper StreamEntriesHelper
 | 
					  helper StreamEntriesHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def mention(mentioned_account, status)
 | 
					  def mention(recipient, notification)
 | 
				
			||||||
    @me     = mentioned_account
 | 
					    @me     = recipient
 | 
				
			||||||
    @status = status
 | 
					    @status = notification.target_status
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return unless @me.user.settings(:notification_emails).mention
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.mention.subject', name: @status.account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.mention.subject', name: @status.account.acct)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def follow(followed_account, follower)
 | 
					  def follow(recipient, notification)
 | 
				
			||||||
    @me      = followed_account
 | 
					    @me      = recipient
 | 
				
			||||||
    @account = follower
 | 
					    @account = notification.from_account
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return unless @me.user.settings(:notification_emails).follow
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow.subject', name: @account.acct)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def favourite(target_status, from_account)
 | 
					  def favourite(recipient, notification)
 | 
				
			||||||
    @me      = target_status.account
 | 
					    @me      = recipient
 | 
				
			||||||
    @account = from_account
 | 
					    @account = notification.from_account
 | 
				
			||||||
    @status  = target_status
 | 
					    @status  = notification.target_status
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return unless @me.user.settings(:notification_emails).favourite
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.favourite.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.favourite.subject', name: @account.acct)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def reblog(target_status, from_account)
 | 
					  def reblog(recipient, notification)
 | 
				
			||||||
    @me      = target_status.account
 | 
					    @me      = recipient
 | 
				
			||||||
    @account = from_account
 | 
					    @account = notification.from_account
 | 
				
			||||||
    @status  = target_status
 | 
					    @status  = notification.target_status
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return unless @me.user.settings(:notification_emails).reblog
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@me.user.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.reblog.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.reblog.subject', name: @account.acct)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								app/models/notification.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								app/models/notification.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Notification < ApplicationRecord
 | 
				
			||||||
 | 
					  include Paginable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  belongs_to :account
 | 
				
			||||||
 | 
					  belongs_to :activity, polymorphic: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  belongs_to :mention,   foreign_type: 'Mention',   foreign_key: 'activity_id'
 | 
				
			||||||
 | 
					  belongs_to :status,    foreign_type: 'Status',    foreign_key: 'activity_id'
 | 
				
			||||||
 | 
					  belongs_to :follow,    foreign_type: 'Follow',    foreign_key: 'activity_id'
 | 
				
			||||||
 | 
					  belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  STATUS_INCLUDES = [:account, :media_attachments, mentions: :account, reblog: [:account, mentions: :account]].freeze
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  scope :with_includes, -> { includes(status: STATUS_INCLUDES, mention: [status: STATUS_INCLUDES], favourite: [:account, status: STATUS_INCLUDES], follow: :account) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def type
 | 
				
			||||||
 | 
					    case activity_type
 | 
				
			||||||
 | 
					    when 'Status'
 | 
				
			||||||
 | 
					      :reblog
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      activity_type.downcase.to_sym
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def from_account
 | 
				
			||||||
 | 
					    case type
 | 
				
			||||||
 | 
					    when :mention
 | 
				
			||||||
 | 
					      activity.status.account
 | 
				
			||||||
 | 
					    when :follow, :favourite, :reblog
 | 
				
			||||||
 | 
					      activity.account
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def target_status
 | 
				
			||||||
 | 
					    case type
 | 
				
			||||||
 | 
					    when :reblog
 | 
				
			||||||
 | 
					      activity.reblog
 | 
				
			||||||
 | 
					    when :favourite, :mention
 | 
				
			||||||
 | 
					      activity.status
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -10,7 +10,7 @@ class FavouriteService < BaseService
 | 
				
			|||||||
    HubPingWorker.perform_async(account.id)
 | 
					    HubPingWorker.perform_async(account.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if status.local?
 | 
					    if status.local?
 | 
				
			||||||
      NotificationMailer.favourite(status, account).deliver_later unless status.account.blocking?(account)
 | 
					      NotifyService.new.call(status.account, favourite)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      NotificationWorker.perform_async(favourite.stream_entry.id, status.account_id)
 | 
					      NotificationWorker.perform_async(favourite.stream_entry.id, status.account_id)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class FollowService < BaseService
 | 
				
			|||||||
    follow = source_account.follow!(target_account)
 | 
					    follow = source_account.follow!(target_account)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if target_account.local?
 | 
					    if target_account.local?
 | 
				
			||||||
      NotificationMailer.follow(target_account, source_account).deliver_later unless target_account.blocking?(source_account)
 | 
					      NotifyService.new.call(target_account, follow)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      subscribe_service.call(target_account)
 | 
					      subscribe_service.call(target_account)
 | 
				
			||||||
      NotificationWorker.perform_async(follow.stream_entry.id, target_account.id)
 | 
					      NotificationWorker.perform_async(follow.stream_entry.id, target_account.id)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								app/services/notify_service.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/services/notify_service.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotifyService < BaseService
 | 
				
			||||||
 | 
					  def call(recipient, activity)
 | 
				
			||||||
 | 
					    @recipient    = recipient
 | 
				
			||||||
 | 
					    @activity     = activity
 | 
				
			||||||
 | 
					    @notification = Notification.new(account: @recipient, activity: @activity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if blocked?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    create_notification
 | 
				
			||||||
 | 
					    send_email if email_enabled?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def blocked?
 | 
				
			||||||
 | 
					    blocked = false
 | 
				
			||||||
 | 
					    blocked ||= @recipient.id == @notification.from_account.id
 | 
				
			||||||
 | 
					    blocked ||= @recipient.blocking?(@notification.from_account)
 | 
				
			||||||
 | 
					    blocked
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def create_notification
 | 
				
			||||||
 | 
					    @notification.save!
 | 
				
			||||||
 | 
					    FeedManager.instance.broadcast(@recipient.id, type: 'notification', message: FeedManager.instance.inline_render(@recipient, 'api/v1/notifications/show', @notification))
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def send_email
 | 
				
			||||||
 | 
					    NotificationMailer.send(@notification.type, @recipient, @notification).deliver_later
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def email_enabled?
 | 
				
			||||||
 | 
					    @recipient.user.settings(:notification_emails).send(@notification.type)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -150,12 +150,10 @@ class ProcessFeedService < BaseService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        next if mentioned_account.nil? || processed_account_ids.include?(mentioned_account.id)
 | 
					        next if mentioned_account.nil? || processed_account_ids.include?(mentioned_account.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if mentioned_account.local?
 | 
					        mention = mentioned_account.mentions.where(status: parent).first_or_create(status: parent)
 | 
				
			||||||
          # Send notifications
 | 
					 | 
				
			||||||
          NotificationMailer.mention(mentioned_account, parent).deliver_later unless mentioned_account.blocking?(parent.account)
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mentioned_account.mentions.where(status: parent).first_or_create(status: parent)
 | 
					        # Notify local user
 | 
				
			||||||
 | 
					        NotifyService.new.call(mentioned_account, mention) if mentioned_account.local?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # So we can skip duplicate mentions
 | 
					        # So we can skip duplicate mentions
 | 
				
			||||||
        processed_account_ids << mentioned_account.id
 | 
					        processed_account_ids << mentioned_account.id
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,8 +65,8 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def follow!(account, target_account)
 | 
					  def follow!(account, target_account)
 | 
				
			||||||
    account.follow!(target_account)
 | 
					    follow = account.follow!(target_account)
 | 
				
			||||||
    NotificationMailer.follow(target_account, account).deliver_later unless target_account.blocking?(account)
 | 
					    NotifyService.new.call(target_account, follow)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unfollow!(account, target_account)
 | 
					  def unfollow!(account, target_account)
 | 
				
			||||||
@@ -83,8 +83,8 @@ class ProcessInteractionService < BaseService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  def favourite!(xml, from_account)
 | 
					  def favourite!(xml, from_account)
 | 
				
			||||||
    current_status = status(xml)
 | 
					    current_status = status(xml)
 | 
				
			||||||
    current_status.favourites.where(account: from_account).first_or_create!(account: from_account)
 | 
					    favourite = current_status.favourites.where(account: from_account).first_or_create!(account: from_account)
 | 
				
			||||||
    NotificationMailer.favourite(current_status, from_account).deliver_later unless current_status.account.blocking?(from_account)
 | 
					    NotifyService.new.call(current_status.account, favourite)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def add_post!(body, account)
 | 
					  def add_post!(body, account)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ class ProcessMentionsService < BaseService
 | 
				
			|||||||
      mentioned_account = mention.account
 | 
					      mentioned_account = mention.account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if mentioned_account.local?
 | 
					      if mentioned_account.local?
 | 
				
			||||||
        NotificationMailer.mention(mentioned_account, status).deliver_later unless mentioned_account.blocking?(status.account)
 | 
					        NotifyService.new.call(mentioned_account, mention)
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
        NotificationWorker.perform_async(status.stream_entry.id, mentioned_account.id)
 | 
					        NotificationWorker.perform_async(status.stream_entry.id, mentioned_account.id)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ class ReblogService < BaseService
 | 
				
			|||||||
    HubPingWorker.perform_async(account.id)
 | 
					    HubPingWorker.perform_async(account.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if reblogged_status.local?
 | 
					    if reblogged_status.local?
 | 
				
			||||||
      NotificationMailer.reblog(reblogged_status, account).deliver_later unless reblogged_status.account.blocking?(account)
 | 
					      NotifyService.new.call(reblogged_status.account, reblog)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      NotificationWorker.perform_async(reblog.stream_entry.id, reblogged_status.account_id)
 | 
					      NotificationWorker.perform_async(reblog.stream_entry.id, reblogged_status.account_id)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								app/views/api/v1/notifications/index.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/api/v1/notifications/index.rabl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					collection @notifications
 | 
				
			||||||
 | 
					extends 'api/v1/notifications/show'
 | 
				
			||||||
							
								
								
									
										11
									
								
								app/views/api/v1/notifications/show.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/views/api/v1/notifications/show.rabl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					object @notification
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					attributes :id, :type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					child from_account: :account do
 | 
				
			||||||
 | 
					  extends 'api/v1/accounts/show'
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					node(:status, if: lambda { |n| [:favourite, :reblog, :mention].include?(n.type) }) do |n|
 | 
				
			||||||
 | 
					  partial 'api/v1/statuses/show', object: n.target_status
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -74,6 +74,8 @@ Rails.application.routes.draw do
 | 
				
			|||||||
      resources :media,    only: [:create]
 | 
					      resources :media,    only: [:create]
 | 
				
			||||||
      resources :apps,     only: [:create]
 | 
					      resources :apps,     only: [:create]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      resources :notifications, only: [:index]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      resources :accounts, only: [:show] do
 | 
					      resources :accounts, only: [:show] do
 | 
				
			||||||
        collection do
 | 
					        collection do
 | 
				
			||||||
          get :relationships
 | 
					          get :relationships
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								db/migrate/20161119211120_create_notifications.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								db/migrate/20161119211120_create_notifications.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					class CreateNotifications < ActiveRecord::Migration[5.0]
 | 
				
			||||||
 | 
					  def change
 | 
				
			||||||
 | 
					    create_table :notifications do |t|
 | 
				
			||||||
 | 
					      t.integer :account_id
 | 
				
			||||||
 | 
					      t.integer :activity_id
 | 
				
			||||||
 | 
					      t.string :activity_type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      t.timestamps
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    add_index :notifications, :account_id
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										11
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								db/schema.rb
									
									
									
									
									
								
							@@ -10,7 +10,7 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# It's strongly recommended that you check this file into your version control system.
 | 
					# It's strongly recommended that you check this file into your version control system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ActiveRecord::Schema.define(version: 20161116162355) do
 | 
					ActiveRecord::Schema.define(version: 20161119211120) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # These are extensions that must be enabled in order to support this database
 | 
					  # These are extensions that must be enabled in order to support this database
 | 
				
			||||||
  enable_extension "plpgsql"
 | 
					  enable_extension "plpgsql"
 | 
				
			||||||
@@ -96,6 +96,15 @@ ActiveRecord::Schema.define(version: 20161116162355) do
 | 
				
			|||||||
    t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree
 | 
					    t.index ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  create_table "notifications", force: :cascade do |t|
 | 
				
			||||||
 | 
					    t.integer  "account_id"
 | 
				
			||||||
 | 
					    t.integer  "activity_id"
 | 
				
			||||||
 | 
					    t.string   "activity_type"
 | 
				
			||||||
 | 
					    t.datetime "created_at",    null: false
 | 
				
			||||||
 | 
					    t.datetime "updated_at",    null: false
 | 
				
			||||||
 | 
					    t.index ["account_id"], name: "index_notifications_on_account_id", using: :btree
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  create_table "oauth_access_grants", force: :cascade do |t|
 | 
					  create_table "oauth_access_grants", force: :cascade do |t|
 | 
				
			||||||
    t.integer  "resource_owner_id", null: false
 | 
					    t.integer  "resource_owner_id", null: false
 | 
				
			||||||
    t.integer  "application_id",    null: false
 | 
					    t.integer  "application_id",    null: false
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								spec/fabricators/notification_fabricator.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								spec/fabricators/notification_fabricator.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					Fabricator(:notification) do
 | 
				
			||||||
 | 
					  activity_id   1
 | 
				
			||||||
 | 
					  activity_type "MyString"
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -7,7 +7,8 @@ RSpec.describe NotificationMailer, type: :mailer do
 | 
				
			|||||||
  let(:own_status)     { Fabricate(:status, account: receiver.account) }
 | 
					  let(:own_status)     { Fabricate(:status, account: receiver.account) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe "mention" do
 | 
					  describe "mention" do
 | 
				
			||||||
    let(:mail) { NotificationMailer.mention(receiver.account, foreign_status) }
 | 
					    let(:mention) { Mention.create!(account: receiver.account, status: foreign_status) }
 | 
				
			||||||
 | 
					    let(:mail) { NotificationMailer.mention(receiver.account, Notification.create!(account: receiver.account, activity: mention)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it "renders the headers" do
 | 
					    it "renders the headers" do
 | 
				
			||||||
      expect(mail.subject).to eq("You were mentioned by bob")
 | 
					      expect(mail.subject).to eq("You were mentioned by bob")
 | 
				
			||||||
@@ -20,7 +21,8 @@ RSpec.describe NotificationMailer, type: :mailer do
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe "follow" do
 | 
					  describe "follow" do
 | 
				
			||||||
    let(:mail) { NotificationMailer.follow(receiver.account, sender) }
 | 
					    let(:follow) { sender.follow!(receiver.account) }
 | 
				
			||||||
 | 
					    let(:mail) { NotificationMailer.follow(receiver.account, Notification.create!(account: receiver.account, activity: follow)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it "renders the headers" do
 | 
					    it "renders the headers" do
 | 
				
			||||||
      expect(mail.subject).to eq("bob is now following you")
 | 
					      expect(mail.subject).to eq("bob is now following you")
 | 
				
			||||||
@@ -33,7 +35,8 @@ RSpec.describe NotificationMailer, type: :mailer do
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe "favourite" do
 | 
					  describe "favourite" do
 | 
				
			||||||
    let(:mail) { NotificationMailer.favourite(own_status, sender) }
 | 
					    let(:favourite) { Favourite.create!(account: sender, status: own_status) }
 | 
				
			||||||
 | 
					    let(:mail) { NotificationMailer.favourite(own_status.account, Notification.create!(account: receiver.account, activity: favourite)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it "renders the headers" do
 | 
					    it "renders the headers" do
 | 
				
			||||||
      expect(mail.subject).to eq("bob favourited your status")
 | 
					      expect(mail.subject).to eq("bob favourited your status")
 | 
				
			||||||
@@ -46,7 +49,8 @@ RSpec.describe NotificationMailer, type: :mailer do
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe "reblog" do
 | 
					  describe "reblog" do
 | 
				
			||||||
    let(:mail) { NotificationMailer.reblog(own_status, sender) }
 | 
					    let(:reblog) { Status.create!(account: sender, reblog: own_status) }
 | 
				
			||||||
 | 
					    let(:mail) { NotificationMailer.reblog(own_status.account, Notification.create!(account: receiver.account, activity: reblog)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    it "renders the headers" do
 | 
					    it "renders the headers" do
 | 
				
			||||||
      expect(mail.subject).to eq("bob reblogged your status")
 | 
					      expect(mail.subject).to eq("bob reblogged your status")
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								spec/models/notification_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								spec/models/notification_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					require 'rails_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RSpec.describe Notification, type: :model do
 | 
				
			||||||
 | 
					  describe '#from_account' do
 | 
				
			||||||
 | 
					    pending
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe '#type' do
 | 
				
			||||||
 | 
					    it 'returns :reblog for a Status' do
 | 
				
			||||||
 | 
					      notification = Notification.new(activity: Status.new)
 | 
				
			||||||
 | 
					      expect(notification.type).to eq :reblog
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'returns :mention for a Mention' do
 | 
				
			||||||
 | 
					      notification = Notification.new(activity: Mention.new)
 | 
				
			||||||
 | 
					      expect(notification.type).to eq :mention
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'returns :favourite for a Favourite' do
 | 
				
			||||||
 | 
					      notification = Notification.new(activity: Favourite.new)
 | 
				
			||||||
 | 
					      expect(notification.type).to eq :favourite
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it 'returns :follow for a Follow' do
 | 
				
			||||||
 | 
					      notification = Notification.new(activity: Follow.new)
 | 
				
			||||||
 | 
					      expect(notification.type).to eq :follow
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
		Reference in New Issue
	
	Block a user