diff options
Diffstat (limited to 'app/models/reaction.rb')
-rw-r--r-- | app/models/reaction.rb | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/app/models/reaction.rb b/app/models/reaction.rb new file mode 100644 index 000000000..184ed2d6e --- /dev/null +++ b/app/models/reaction.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006- Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +class Reaction < ApplicationRecord + belongs_to :reactable, polymorphic: true + belongs_to :user + + validates :reactable_type, inclusion: { in: Redmine::Reaction::REACTABLE_TYPES } + + scope :by, ->(user) { where(user: user) } + scope :for_reactable, ->(reactable) { where(reactable: reactable) } + scope :visible, ->(user) { where(user: User.visible(user)) } + + # Represents reaction details for a reactable object + Detail = Struct.new( + # Users who reacted and are visible to the target user + :visible_users, + # Reaction of the target user + :user_reaction + ) do + def initialize(visible_users: [], user_reaction: nil) + super + end + + def reaction_count = visible_users.size + end + + def self.build_detail_map_for(reactables, user) + reactions = visible(user) + .for_reactable(reactables) + .preload(:user) + .select(:id, :reactable_id, :user_id) + .order(id: :desc) + + reactions.each_with_object({}) do |reaction, m| + m[reaction.reactable_id] ||= Detail.new + + m[reaction.reactable_id].then do |detail| + detail.visible_users << reaction.user + detail.user_reaction = reaction if reaction.user == user + end + end + end +end |