Move send new badge achievement notification to ActiveJob (#2474)

This commit is contained in:
rhymes 2019-04-29 16:51:08 +02:00 committed by Mac Siri
parent 30dcb23169
commit 743316b528
10 changed files with 175 additions and 23 deletions

View file

@ -0,0 +1,12 @@
module Notifications
class NewBadgeAchievementJob < ApplicationJob
queue_as :send_new_badge_achievement_notification
def perform(badge_achievement_id, service = NewBadgeAchievement::Send)
badge_achievement = BadgeAchievement.find_by(id: badge_achievement_id)
return unless badge_achievement
service.call(badge_achievement)
end
end
end

View file

@ -1,6 +1,7 @@
module Notifications
class NewCommentJob < ApplicationJob
queue_as :send_new_comment_notification
def perform(comment_id, service = NewComment::Send)
comment = Comment.find_by(id: comment_id)
service.call(comment) if comment

View file

@ -1,6 +1,7 @@
module Notifications
class NewReactionJob < ApplicationJob
queue_as :send_new_reaction_notification
# @param reaction_data [Hash]
# * :reactable_id [Integer] - article or comment id
# * :reactable_type [String] - "Article" or "Comment"

View file

@ -25,7 +25,7 @@ class BadgeAchievement < ApplicationRecord
private
def notify_recipient
Notification.send_new_badge_notification(self)
Notification.send_new_badge_achievement_notification(self)
end
def send_email_notification

View file

@ -19,6 +19,8 @@ class Notification < ApplicationRecord
end
def send_new_follower_notification_without_delay(follow, is_read = false)
return unless Follow.need_new_follower_notification_for?(follow.followable_type)
follow_data = follow.attributes.slice("follower_id", "followable_id", "followable_type").symbolize_keys
Notifications::NewFollowerJob.perform_now(follow_data, is_read)
end
@ -60,28 +62,20 @@ class Notification < ApplicationRecord
Notifications::NewCommentJob.perform_now(comment.id)
end
def send_new_badge_notification(badge_achievement)
json_data = {
user: user_data(badge_achievement.user),
badge_achievement: {
badge_id: badge_achievement.badge_id,
rewarding_context_message: badge_achievement.rewarding_context_message,
badge: {
title: badge_achievement.badge.title,
description: badge_achievement.badge.description,
badge_image_url: badge_achievement.badge.badge_image_url
}
}
}
Notification.create(
user_id: badge_achievement.user.id,
notifiable_id: badge_achievement.id,
notifiable_type: "BadgeAchievement",
action: nil,
json_data: json_data,
)
def send_new_badge_achievement_notification(badge_achievement)
Notifications::NewBadgeAchievementJob.perform_later(badge_achievement.id)
end
# NOTE: this alias is temporary until the transition to ActiveJob is completed
# and all old DelayedJob jobs are processed by the queue workers.
# It can be removed after pre-existing jobs are done
alias send_new_badge_notification send_new_badge_achievement_notification
# NOTE: this method is temporary until the transition to ActiveJob is completed
# and all old DelayedJob jobs are processed by the queue workers.
# It can be removed after pre-existing jobs are done
def send_new_badge_notification_without_delay(badge_achievement)
Notifications::NewBadgeAchievementJob.perform_now(badge_achievement.id)
end
handle_asynchronously :send_new_badge_notification
def send_reaction_notification(reaction, receiver)
return if reaction.skip_notification_for?(receiver)

View file

@ -0,0 +1,45 @@
# send notifications about the new badge achievement
module Notifications
module NewBadgeAchievement
class Send
def initialize(badge_achievement)
@badge_achievement = badge_achievement
end
delegate :user_data, to: Notifications
def self.call(*args)
new(*args).call
end
def call
Notification.create(
user_id: badge_achievement.user.id,
notifiable_id: badge_achievement.id,
notifiable_type: "BadgeAchievement",
action: nil,
json_data: json_data,
)
end
private
attr_reader :badge_achievement
def json_data
{
user: user_data(badge_achievement.user),
badge_achievement: {
badge_id: badge_achievement.badge_id,
rewarding_context_message: badge_achievement.rewarding_context_message,
badge: {
title: badge_achievement.badge.title,
description: badge_achievement.badge.description,
badge_image_url: badge_achievement.badge.badge_image_url
}
}
}
end
end
end
end

View file

@ -0,0 +1,24 @@
require "rails_helper"
RSpec.describe Notifications::NewBadgeAchievementJob, type: :job do
include_examples "#enqueues_job", "send_new_badge_achievement_notification", 5
describe "#perform_now" do
let(:new_badge_service) { double }
before do
allow(new_badge_service).to receive(:call)
end
it "calls the service" do
badge_achievement = create(:badge_achievement)
described_class.perform_now(badge_achievement.id, new_badge_service)
expect(new_badge_service).to have_received(:call).with(badge_achievement).once
end
it "doesn't call a service if a nonexistent badge achievement is passed" do
described_class.perform_now(9999, new_badge_service)
expect(new_badge_service).not_to have_received(:call)
end
end
end

View file

@ -7,6 +7,7 @@ RSpec.describe Notification, type: :model do
let(:organization) { create(:organization) }
let(:article) { create(:article, user_id: user.id, page_views_count: 4000, positive_reactions_count: 70) }
let(:follow_instance) { user.follow(user2) }
let(:badge_achievement) { create(:badge_achievement) }
describe "when trying to #send_new_follower_notification after following a tag" do
let(:tag) { create(:tag) }
@ -425,4 +426,28 @@ RSpec.describe Notification, type: :model do
expect(notification.aggregated?).to eq false
end
end
describe "#send_new_badge_achievement_notification" do
it "enqueues a new badge achievement job" do
assert_enqueued_with(job: Notifications::NewBadgeAchievementJob, args: [badge_achievement.id]) do
Notification.send_new_badge_achievement_notification(badge_achievement)
end
end
end
describe "#send_new_badge_notification (deprecated)" do
it "enqueues a new badge achievement job" do
assert_enqueued_with(job: Notifications::NewBadgeAchievementJob, args: [badge_achievement.id]) do
Notification.send_new_badge_notification(badge_achievement)
end
end
end
describe "#send_new_badge_notification_without_delay (deprecated)" do
it "creates a notification" do
expect do
Notification.send_new_badge_notification_without_delay(badge_achievement)
end.to change(Notification, :count).by(1)
end
end
end

View file

@ -221,7 +221,9 @@ RSpec.describe "NotificationsIndex", type: :request do
sign_in user
badge = create(:badge)
badge_achievement = create(:badge_achievement, user: user, badge: badge)
Notification.send_new_badge_notification_without_delay(badge_achievement)
perform_enqueued_jobs do
Notification.send_new_badge_achievement_notification(badge_achievement)
end
get "/notifications"
end

View file

@ -0,0 +1,48 @@
require "rails_helper"
RSpec.describe Notifications::NewBadgeAchievement::Send, type: :service do
let(:badge_achievement) { create(:badge_achievement) }
def expected_json_data
{
user: Notifications.user_data(badge_achievement.user),
badge_achievement: {
badge_id: badge_achievement.badge_id,
rewarding_context_message: badge_achievement.rewarding_context_message,
badge: {
title: badge_achievement.badge.title,
description: badge_achievement.badge.description,
badge_image_url: badge_achievement.badge.badge_image_url
}
}
}.to_json
end
it "creates a notification" do
expect do
described_class.call(badge_achievement)
end.to change(Notification, :count).by(1)
end
it "creates a notification for the badge achievement user" do
notification = described_class.call(badge_achievement)
expect(notification.user).to eq(badge_achievement.user)
end
it "creates a notification for the badge achievement" do
notification = described_class.call(badge_achievement)
expect(notification.notifiable_id).to eq(badge_achievement.id)
expect(notification.notifiable_type).to eq("BadgeAchievement")
end
it "creates a notification with no action" do
notification = described_class.call(badge_achievement)
expect(notification.action).to be(nil)
end
it "creates a notification with the proper json data" do
notification = described_class.call(badge_achievement)
json_data = notification.json_data.to_json
expect(JSON.parse(json_data)).to eq(JSON.parse(expected_json_data))
end
end