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 ) }
scope :recent , lambda { order ( 'created_at desc' ) . limit ( 10 ) }
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
@types || = Enum . new (
:mentioned , :replied , :quoted , :edited , :liked , :private_message ,
:invited_to_private_message , :invitee_accepted , :posted , :moved_post
)
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 )
2013-07-01 20:45:52 +02:00
Notification . where ( user_id : user . id , topic_id : topic_id , post_number : post_numbers , read : false ) . update_all " read = 't' "
2013-02-05 14:16:51 -05:00
end
def self . interesting_after ( min_date )
result = where ( " created_at > ? " , min_date )
. includes ( :topic )
. 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
# Be wary of calling this frequently. O(n) JSON parsing can suck.
def data_hash
@data_hash || = begin
return nil if data . blank?
2013-02-28 21:54:12 +03:00
JSON . parse ( data ) . with_indifferent_access
2013-02-05 14:16:51 -05:00
end
end
def text_description
link = block_given? ? yield : " "
2013-03-01 15:07:44 +03:00
I18n . t ( " notification_types. #{ Notification . types [ notification_type ] } " , data_hash . merge ( link : link ) )
2013-02-05 14:16:51 -05:00
end
def url
if topic . present?
return topic . relative_url ( post_number )
end
end
def post
2013-02-28 21:54:12 +03:00
return if topic_id . blank? || post_number . blank?
2013-02-05 14:16:51 -05:00
Post . where ( topic_id : topic_id , post_number : post_number ) . first
end
2013-05-16 15:03:03 +10:00
protected
def refresh_notification_count
user_id = user . id
MessageBus . publish ( " /notification/ #{ user_id } " ,
{ unread_notifications : user . unread_notifications ,
unread_private_messages : user . unread_private_messages } ,
user_ids : [ user_id ] # only publish the notification to this user
)
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
# created_at :datetime not null
# updated_at :datetime not null
# topic_id :integer
# post_number :integer
# post_action_id :integer
#
# Indexes
#
# index_notifications_on_post_action_id (post_action_id)
# index_notifications_on_user_id_and_created_at (user_id,created_at)
#