← Back to Upcase

Asking feedback on building notifications system?


(Samnang Chhun) #1

I’m building a notifications system for an social networking app, here is what I got so far:

# app/controllers/v1/comments_controller.rb
class V1::CommentsController < ApplicationController
  def create
    post    = load_post
    comment = post.comments.new(protected_params)
    comment.user = current_user
    if comment.save
      create_notification(
        user_ids: post.subscriber_ids,
        action:   :make_comment,
        target:   post
      )
      render_created(comment)
    else
      render_bad_request(comment)
    end
  end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  def create_notification(user_ids:, action:, target:)
    NotificationsWorker.perform_async(
      current_user.id,
      user_ids,
      action,
      target.class.name,
      target.id
    )
  end
end
# app/workers/notifications_worker.rb
class NotificationsWorker
  include Sidekiq::Worker
  sidekiq_options queue: :notification
 
  def perform(actor_id, user_ids, action, target_type, target_id)
    actor  = User.find(actor_id)
    target = target_type.constantize.find(target_id)
 
    notifications = []
    ActiveRecord::Base.transaction do
      user_ids.each do |user_id|
        notification = Notification.create(
          user_id: user_id,
          action:  action,
          actor:   actor,
          target:  target
        )
 
        notifications.push(PushNotification.new(notification).notification)
      end
    end
 
    Urbanairship.batch_push(notifications)
  end
end
# app/models/push_notification.rb
class PushNotification
  def initialize(notification)
    @notification = notification
  end
 
  delegate :actor, :target, to: :@notification
 
  def notification
    {
      aliases: [@notification.user_id],
      aps: { alert: alert_message, badge: '+1' },
      meta: {
        action: @notification.action,
        target.class.name => target.id
      }
    }
  end
 
  private
 
  def alert_message
    case @notification.action
    when 'follow_user'
      "#{actor.short_name} started following #{target.name}"
    when 'like_post'
      "#{actor.short_name} likes #{target.dog.name}'s status"
    when 'make_comment'
      "#{actor.short_name} commented on #{target.dog.name}'s status"
    end
  end
end

In this particular example, whenever a user comments on someone else’s post, they will register in subscribers list and notify all existing subscribers. I feel I’m not quiet happy about this design yet. So I hope to get some feedbacks from you guys here and share similar experiences on building notifications in your apps?

Sorry to have a quiet long post like this :smile: