2024-02-25 12:15:55 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-03-10 14:31:47 -04:00
|
|
|
class FavoriteManager
|
2023-01-28 09:37:20 -05:00
|
|
|
ISOLATION = Rails.env.test? ? {} : { isolation: :repeatable_read }
|
|
|
|
|
|
|
|
def self.add!(user:, post:, force: false)
|
2020-03-18 22:12:34 -04:00
|
|
|
retries = 5
|
2020-03-10 14:31:47 -04:00
|
|
|
begin
|
2023-01-28 09:37:20 -05:00
|
|
|
Favorite.transaction(**ISOLATION) do
|
2020-03-10 14:31:47 -04:00
|
|
|
unless force
|
|
|
|
if user.favorite_count >= user.favorite_limit
|
|
|
|
raise Favorite::Error, "You can only keep up to #{user.favorite_limit} favorites."
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-12 20:32:02 -04:00
|
|
|
Favorite.create(:user_id => user.id, :post_id => post.id)
|
2020-03-10 14:31:47 -04:00
|
|
|
post.append_user_to_fav_string(user.id)
|
|
|
|
post.do_not_version_changes = true
|
|
|
|
post.save
|
|
|
|
end
|
2020-03-18 22:27:04 -04:00
|
|
|
rescue ActiveRecord::SerializationFailure => e
|
2020-03-18 22:12:34 -04:00
|
|
|
retries -= 1
|
|
|
|
retry if retries > 0
|
2020-03-18 22:27:04 -04:00
|
|
|
raise e
|
2020-03-10 14:31:47 -04:00
|
|
|
rescue ActiveRecord::RecordNotUnique
|
|
|
|
raise Favorite::Error, "You have already favorited this post" unless force
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-08-01 13:32:24 -04:00
|
|
|
def self.remove!(user:, post:)
|
2020-03-18 22:12:34 -04:00
|
|
|
retries = 5
|
|
|
|
begin
|
2023-01-28 09:37:20 -05:00
|
|
|
Favorite.transaction(**ISOLATION) do
|
2023-08-01 13:32:24 -04:00
|
|
|
unless Favorite.for_user(user.id).where(user_id: user.id, post_id: post.id).exists?
|
2020-03-18 22:12:34 -04:00
|
|
|
return
|
|
|
|
end
|
2020-03-10 14:31:47 -04:00
|
|
|
|
2023-08-01 13:32:24 -04:00
|
|
|
Favorite.for_user(user.id).where(post_id: post.id).destroy_all
|
|
|
|
post.delete_user_from_fav_string(user.id)
|
2020-03-18 22:12:34 -04:00
|
|
|
post.do_not_version_changes = true
|
2023-08-01 13:32:24 -04:00
|
|
|
post.save
|
2020-03-18 22:12:34 -04:00
|
|
|
end
|
2020-03-18 22:27:04 -04:00
|
|
|
rescue ActiveRecord::SerializationFailure => e
|
2020-03-18 22:12:34 -04:00
|
|
|
retries -= 1
|
|
|
|
retry if retries > 0
|
2020-03-18 22:27:04 -04:00
|
|
|
raise e
|
2020-03-10 14:31:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-01-28 09:37:20 -05:00
|
|
|
def self.give_to_parent!(post)
|
2020-03-10 14:31:47 -04:00
|
|
|
# TODO Much better and more intelligent logic can exist for this
|
|
|
|
parent = post.parent
|
|
|
|
return false unless parent
|
|
|
|
post.favorites.each do |fav|
|
2020-03-10 15:16:05 -04:00
|
|
|
tries = 5
|
|
|
|
begin
|
2023-01-28 09:37:20 -05:00
|
|
|
FavoriteManager.remove!(user: fav.user, post: post)
|
|
|
|
FavoriteManager.add!(user: fav.user, post: parent, force: true)
|
2020-03-10 15:16:05 -04:00
|
|
|
rescue ActiveRecord::SerializationFailure
|
|
|
|
tries -= 1
|
|
|
|
retry if tries > 0
|
|
|
|
end
|
2020-03-10 14:31:47 -04:00
|
|
|
end
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|