diaspora/app/models/notification.rb

121 lines
3.9 KiB
Ruby

# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
#
class Notification < ActiveRecord::Base
belongs_to :recipient, class_name: "User"
has_many :notification_actors, dependent: :destroy
has_many :actors, class_name: "Person", through: :notification_actors, source: :person
belongs_to :target, polymorphic: true
attr_accessor :note_html
def self.for(recipient, opts={})
where(opts.merge!(recipient_id: recipient.id)).order("updated_at DESC")
end
def self.notify(recipient, target, actor)
return nil unless target.respond_to?(:notification_type) && recipient.person != actor
note_type = target.notification_type(recipient, actor)
return nil unless note_type
return_note = if [Comment, Like, Reshare].any? { |klass| target.is_a?(klass) }
s_target = target.is_a?(Reshare) ? target.root : target.parent
note_type.concatenate_or_create(recipient, s_target,
actor, note_type)
else
note_type.make_notification(recipient, target,
actor, note_type)
end
return_note.email_the_user(target, actor) if return_note
return_note
end
def as_json(opts={})
super(opts.merge(methods: :note_html))
end
def email_the_user(target, actor)
recipient.mail(mail_job, recipient_id, actor.id, target.id)
end
def set_read_state( read_state )
update_column(:unread, !read_state)
end
def mail_job
raise NotImplementedError.new("Subclass this.")
end
def linked_object
target
end
def self.concatenate_or_create(recipient, target, actor, notification_type)
return nil if suppress_notification?(recipient, target)
if n = notification_type.where(:target_id => target.id,
:target_type => target.class.base_class,
:recipient_id => recipient.id,
:unread => true).first
begin
n.actors = n.actors | [actor]
n.unread = true
# Explicitly touch the notification to update updated_at whenever new actor is inserted in notification.
n.touch
n.save!
rescue ActiveRecord::RecordNotUnique
nil
end
n
else
make_notification(recipient, target, actor, notification_type)
end
end
def self.make_notification(recipient, target, actor, notification_type)
return nil if suppress_notification?(recipient, target)
n = notification_type.new(:target => target,
:recipient_id => recipient.id)
n.actors = n.actors | [actor]
n.unread = false if target.is_a? Request
n.save!
n
end
def self.concatenate_or_create(recipient, target, actor)
return nil if suppress_notification?(recipient, target)
find_or_initialize_by(recipient: recipient, target: target, unread: true).tap do |notification|
notification.actors |= [actor]
# Explicitly touch the notification to update updated_at whenever new actor is inserted in notification.
if notification.new_record? || notification.changed?
notification.save!
else
notification.touch
end
end
end
def self.create_notification(recipient_id, target, actor)
create(recipient_id: recipient_id, target: target, actors: [actor])
end
def self.suppress_notification?(recipient, post)
post.is_a?(Post) && recipient.is_shareable_hidden?(post)
end
private_class_method :suppress_notification?
def self.types
{
"also_commented" => "Notifications::AlsoCommented",
"comment_on_post" => "Notifications::CommentOnPost",
"liked" => "Notifications::Liked",
"mentioned" => "Notifications::Mentioned",
"reshared" => "Notifications::Reshared",
"started_sharing" => "Notifications::StartedSharing"
}
end
end