awardable.rb 3.4 KB
Newer Older
1 2
# frozen_string_literal: true

3 4 5 6
module Awardable
  extend ActiveSupport::Concern

  included do
7
    has_many :award_emoji, -> { includes(:user).order(:id) }, as: :awardable, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
8 9

    if self < Participable
10 11
      # By default we always load award_emoji user association
      participant :award_emoji
12 13 14
    end
  end

15
  class_methods do
H
Heinrich Lee Yu 已提交
16
    def awarded(user, name = nil)
H
Hiroyuki Sato 已提交
17 18 19 20 21
      sql = <<~EOL
        EXISTS (
          SELECT TRUE
          FROM award_emoji
          WHERE user_id = :user_id AND
H
Heinrich Lee Yu 已提交
22
                #{"name = :name AND" if name.present?}
H
Hiroyuki Sato 已提交
23 24 25 26 27 28 29 30
                awardable_type = :awardable_type AND
                awardable_id = #{self.arel_table.name}.id
        )
      EOL

      where(sql, user_id: user.id, name: name, awardable_type: self.name)
    end

31 32 33 34 35 36 37 38 39 40 41 42 43 44
    def not_awarded(user)
      sql = <<~EOL
        NOT EXISTS (
          SELECT TRUE
          FROM award_emoji
          WHERE user_id = :user_id AND
                awardable_type = :awardable_type AND
                awardable_id = #{self.arel_table.name}.id
        )
      EOL

      where(sql, user_id: user.id, awardable_type: self.name)
    end

45
    def order_upvotes_desc
46 47 48 49 50
      order_votes(AwardEmoji::UPVOTE_NAME, 'DESC')
    end

    def order_upvotes_asc
      order_votes(AwardEmoji::UPVOTE_NAME, 'ASC')
51 52 53
    end

    def order_downvotes_desc
54
      order_votes(AwardEmoji::DOWNVOTE_NAME, 'DESC')
55 56
    end

57 58
    # Order votes by emoji, optional sort order param `descending` defaults to true
    def order_votes(emoji_name, direction)
59 60 61 62 63 64 65 66 67 68 69
      awardable_table = self.arel_table
      awards_table = AwardEmoji.arel_table

      join_clause = awardable_table.join(awards_table, Arel::Nodes::OuterJoin).on(
        awards_table[:awardable_id].eq(awardable_table[:id]).and(
          awards_table[:awardable_type].eq(self.name).and(
            awards_table[:name].eq(emoji_name)
          )
        )
      ).join_sources

70
      joins(join_clause).group(awardable_table[:id]).reorder("COUNT(award_emoji.id) #{direction}")
71 72 73
    end
  end

Z
Zeger-Jan van de Weg 已提交
74
  def grouped_awards(with_thumbs: true)
75 76
    # By default we always load award_emoji user association
    awards = award_emoji.group_by(&:name)
77 78

    if with_thumbs
Z
Zeger-Jan van de Weg 已提交
79 80
      awards[AwardEmoji::UPVOTE_NAME]   ||= []
      awards[AwardEmoji::DOWNVOTE_NAME] ||= []
81 82 83 84 85 86
    end

    awards
  end

  def downvotes
Z
Zeger-Jan van de Weg 已提交
87
    award_emoji.downvotes.count
88 89 90
  end

  def upvotes
Z
Zeger-Jan van de Weg 已提交
91
    award_emoji.upvotes.count
92 93 94 95 96 97
  end

  def emoji_awardable?
    true
  end

98 99
  def user_can_award?(current_user)
    Ability.allowed?(current_user, :award_emoji, self)
B
barthc 已提交
100 101
  end

102 103 104 105 106 107
  def user_authored?(current_user)
    author = self.respond_to?(:author) ? self.author : self.user

    author == current_user
  end

108 109 110 111 112 113
  def awarded_emoji?(emoji_name, current_user)
    award_emoji.where(name: emoji_name, user: current_user).exists?
  end

  def create_award_emoji(name, current_user)
    return unless emoji_awardable?
114

D
dixpac 已提交
115
    award_emoji.create(name: normalize_name(name), user: current_user)
116 117 118
  end

  def remove_award_emoji(name, current_user)
119
    award_emoji.where(name: name, user: current_user).destroy_all # rubocop: disable DestroyAll
120 121 122 123 124 125 126 127 128
  end

  def toggle_award_emoji(emoji_name, current_user)
    if awarded_emoji?(emoji_name, current_user)
      remove_award_emoji(emoji_name, current_user)
    else
      create_award_emoji(emoji_name, current_user)
    end
  end
D
dixpac 已提交
129 130 131 132

  private

  def normalize_name(name)
E
Eric Eastwood 已提交
133
    Gitlab::Emoji.normalize_emoji_name(name)
D
dixpac 已提交
134
  end
135
end