2013-03-01 15:07:44 +03:00
require_dependency 'enum'
2013-02-07 16:45:24 +01:00
2013-03-01 15:07:44 +03:00
class Notification < ActiveRecord :: Base
2013-02-05 14:16:51 -05:00
belongs_to :user
belongs_to :topic
validates_presence_of :data
validates_presence_of :notification_type
2013-02-28 21:54:12 +03:00
scope :unread , lambda { where ( read : false ) }
2015-06-22 14:32:45 +02:00
scope :recent , lambda { | n = nil | n || = 10 ; order ( 'notifications.created_at desc' ) . limit ( n ) }
2015-06-23 06:14:22 +10:00
scope :visible , lambda { joins ( 'LEFT JOIN topics ON notifications.topic_id = topics.id' )
. where ( 'topics.id IS NULL OR topics.deleted_at IS NULL' ) }
2013-02-28 21:54:12 +03:00
2013-05-16 15:03:03 +10:00
after_save :refresh_notification_count
after_destroy :refresh_notification_count
2013-05-16 17:50:14 +10:00
def self . ensure_consistency!
Notification . exec_sql ( "
DELETE FROM Notifications n WHERE notification_type = :id AND
NOT EXISTS (
SELECT 1 FROM posts p
JOIN topics t ON t . id = p . topic_id
WHERE p . deleted_at is null AND t . deleted_at IS NULL
AND p . post_number = n . post_number AND t . id = n . topic_id
) " , id: Notification.types[:private_message])
end
2013-03-01 15:07:44 +03:00
def self . types
2016-01-08 16:23:52 +05:30
@types || = Enum . new ( mentioned : 1 ,
replied : 2 ,
quoted : 3 ,
edited : 4 ,
liked : 5 ,
private_message : 6 ,
invited_to_private_message : 7 ,
invitee_accepted : 8 ,
posted : 9 ,
moved_post : 10 ,
linked : 11 ,
granted_badge : 12 ,
invited_to_topic : 13 ,
custom : 14 ,
2016-01-27 21:38:14 +11:00
group_mentioned : 15 ,
2016-07-06 15:56:40 -04:00
group_message_summary : 16 ,
watching_first_post : 17
2016-01-27 21:38:14 +11:00
)
2013-02-05 14:16:51 -05:00
end
2013-02-25 18:42:42 +11:00
def self . mark_posts_read ( user , topic_id , post_numbers )
2016-01-06 10:22:03 +11:00
count = Notification
. where ( user_id : user . id ,
topic_id : topic_id ,
post_number : post_numbers ,
read : false )
. update_all ( " read = 't' " )
user . publish_notifications_state if count > 0
2016-01-06 20:33:55 +11:00
count
2013-02-05 14:16:51 -05:00
end
def self . interesting_after ( min_date )
result = where ( " created_at > ? " , min_date )
. includes ( :topic )
2015-02-19 12:40:00 +11:00
. visible
2013-02-05 14:16:51 -05:00
. unread
. limit ( 20 )
2013-03-01 15:07:44 +03:00
. order ( " CASE WHEN notification_type = #{ Notification . types [ :replied ] } THEN 1
WHEN notification_type = #{Notification.types[:mentioned]} THEN 2
2013-02-05 14:16:51 -05:00
ELSE 3
END , created_at DESC " ).to_a
# Remove any duplicates by type and topic
if result . present?
2013-02-07 16:45:24 +01:00
seen = { }
2013-02-05 14:16:51 -05:00
to_remove = Set . new
result . each do | r |
seen [ r . notification_type ] || = Set . new
if seen [ r . notification_type ] . include? ( r . topic_id )
2013-02-07 16:45:24 +01:00
to_remove << r . id
2013-02-05 14:16:51 -05:00
else
seen [ r . notification_type ] << r . topic_id
end
end
2013-02-07 16:45:24 +01:00
result . reject! { | r | to_remove . include? ( r . id ) }
2013-02-05 14:16:51 -05:00
end
result
end
2014-05-26 13:26:28 -04:00
# Clean up any notifications the user can no longer see. For example, if a topic was previously
# public then turns private.
def self . remove_for ( user_id , topic_id )
Notification . where ( user_id : user_id , topic_id : topic_id ) . delete_all
end
2013-02-05 14:16:51 -05:00
# Be wary of calling this frequently. O(n) JSON parsing can suck.
def data_hash
@data_hash || = begin
return nil if data . blank?
2016-02-23 01:34:16 +01:00
2015-09-04 13:34:21 +10:00
parsed = JSON . parse ( data )
return nil if parsed . blank?
parsed . with_indifferent_access
2013-02-05 14:16:51 -05:00
end
end
def url
2016-02-01 19:12:10 +01:00
topic . relative_url ( post_number ) if topic . present?
2013-02-05 14:16:51 -05:00
end
def post
2013-02-28 21:54:12 +03:00
return if topic_id . blank? || post_number . blank?
2014-05-06 14:41:59 +01:00
Post . find_by ( topic_id : topic_id , post_number : post_number )
2013-02-05 14:16:51 -05:00
end
2013-05-16 15:03:03 +10:00
2014-02-13 17:12:17 +11:00
def self . recent_report ( user , count = nil )
2016-03-06 09:21:38 +11:00
return unless user && user . user_option
2014-02-14 07:20:56 +11:00
count || = 10
2015-02-19 12:40:00 +11:00
notifications = user . notifications
. visible
. recent ( count )
. includes ( :topic )
2016-03-06 09:21:38 +11:00
if user . user_option . like_notification_frequency == UserOption . like_notification_frequency_type [ :never ]
notifications = notifications . where ( 'notification_type <> ?' , Notification . types [ :liked ] )
end
notifications = notifications . to_a
2014-02-13 17:12:17 +11:00
if notifications . present?
2016-02-15 19:29:35 +11:00
ids = Notification . exec_sql ( "
SELECT n . id FROM notifications n
WHERE
n . notification_type = 6 AND
n . user_id = #{user.id.to_i} AND
NOT read
ORDER BY n . id ASC
LIMIT #{count.to_i}
" ).values.map do |x,_|
x . to_i
end
if ids . length > 0
notifications += user
. notifications
. order ( 'notifications.created_at DESC' )
. where ( id : ids )
. joins ( :topic )
. limit ( count )
end
notifications . uniq ( & :id ) . sort do | x , y |
2014-02-13 17:27:35 +11:00
if x . unread_pm? && ! y . unread_pm?
- 1
elsif y . unread_pm? && ! x . unread_pm?
1
else
y . created_at < = > x . created_at
end
end . take ( count )
else
[ ]
end
2014-02-13 17:12:17 +11:00
end
def unread_pm?
Notification . types [ :private_message ] == self . notification_type && ! read
end
2013-05-16 15:03:03 +10:00
2016-01-27 12:19:49 +11:00
def post_id
Post . where ( topic : topic_id , post_number : post_number ) . pluck ( :id ) . first
end
2013-05-16 15:03:03 +10:00
protected
def refresh_notification_count
2014-05-23 11:34:34 +10:00
user . publish_notifications_state
2013-05-16 15:03:03 +10:00
end
2013-02-05 14:16:51 -05:00
end
2013-05-24 12:48:32 +10:00
# == Schema Information
#
# Table name: notifications
#
# id :integer not null, primary key
# notification_type :integer not null
# user_id :integer not null
# data :string(1000) not null
# read :boolean default(FALSE), not null
2014-08-27 15:19:25 +10:00
# created_at :datetime not null
# updated_at :datetime not null
2013-05-24 12:48:32 +10:00
# topic_id :integer
# post_number :integer
# post_action_id :integer
#
# Indexes
#
2015-09-18 10:41:10 +10:00
# idx_notifications_speedup_unread_count (user_id,notification_type)
# index_notifications_on_post_action_id (post_action_id)
# index_notifications_on_user_id_and_created_at (user_id,created_at)
2016-02-23 10:33:53 +11:00
# index_notifications_on_user_id_and_id (user_id,id) UNIQUE
2015-09-18 10:41:10 +10:00
# index_notifications_on_user_id_and_topic_id_and_post_number (user_id,topic_id,post_number)
2013-05-24 12:48:32 +10:00
#