Last active
August 20, 2020 09:03
-
-
Save absk1317/5f8f78ff435bd823bf644e0bea080125 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
class BaseObserver < ActiveRecord::Observer | |
def create?(resource) | |
resource.send(:transaction_include_any_action?, [:create]) | |
end | |
def deleted?(resource) | |
resource.send(:transaction_include_any_action?, [:destroy]) | |
end | |
end | |
class LikeObserver < BaseObserver | |
def after_commit(like) | |
commit_actions(like.id) | |
return unless create?(like) | |
create_actions(like.id) | |
end | |
def commit_actions(like_id) | |
AsyncWorker.perform_in(1.minutes, like_id, :update_indices) | |
end | |
def create_actions(like_id) | |
## to avoid false likes, ie. likes that users create by mistake | |
AsyncWorker.perform_in(5.seconds, like_id, :create_notification) | |
end | |
class AsyncWorker | |
include Sidekiq::Worker | |
# retry false, at times users unlike the entity just as they like, and object is deleted in that case | |
# and this job keeps failing. This will prevent that. | |
sidekiq_options retry: false | |
attr_accessor :like | |
def perform(id, method_name) | |
@like = Like.find_by(id: id) | |
return unless like | |
send(method_name) | |
end | |
def create_notification | |
notification = Notification.created_today.likes.find_by(notifiable: like.likeable) | |
if notification | |
# notify only for first like per entity in the day, make rest in-app | |
notification.update!(notifier: like.user, | |
key: "#{like.likeable.likes.created_today.count}_like", | |
notification_type: 'in_app') | |
else | |
Notification.create!(notifier: like.user, | |
key: 'like', | |
target: like.likeable.user, | |
notifiable: like.likeable) | |
end | |
end | |
def update_indices | |
return unless %w[Class1 Class2].include?(like.likeable_type) | |
like.likeable.reindex | |
end | |
end | |
end | |
## specs | |
require 'rails_helper' | |
describe Like, type: :model do | |
include RequestSpecHelper | |
describe 'Associations' do | |
it { is_expected.to belong_to(:user) } | |
it { is_expected.to belong_to(:likeable) } | |
it { is_expected.to have_many(:notifications) } | |
it { is_expected.to validate_inclusion_of(:likeable_type).in_array(Like::LIKEABLES.values.map(&:name)) } | |
end | |
describe 'Callbacks' do | |
let!(:like) { create(:like, likeable: create(:post), user: create(:user)) } | |
it 'adds a notification' do | |
Sidekiq::Testing.inline! | |
expect { like.run_callbacks(:commit) }.to change { Notification.count }.by(1) | |
expect(strip_html(Notification.last.content)).to include('liked your post') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment