summaryrefslogtreecommitdiffstats
path: root/app/models/reaction.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/reaction.rb')
-rw-r--r--app/models/reaction.rb60
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