diff options
author | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2016-04-16 22:09:08 +0300 |
---|---|---|
committer | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2016-05-06 11:47:11 +0300 |
commit | 3bdc57f0a710b3769381ecad7ea4098223ecff56 (patch) | |
tree | abfe22d7d40c7d3e2912d659b045273254767dea /app/models | |
parent | 05920a7964a039fd65d6b665c2ebd130d5ef949c (diff) |
Create table for award emoji
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/award_emoji.rb | 35 | ||||
-rw-r--r-- | app/models/concerns/awardable.rb | 81 | ||||
-rw-r--r-- | app/models/concerns/issuable.rb | 32 | ||||
-rw-r--r-- | app/models/merge_request.rb | 1 | ||||
-rw-r--r-- | app/models/note.rb | 53 | ||||
-rw-r--r-- | app/models/user.rb | 1 |
6 files changed, 130 insertions, 73 deletions
diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb new file mode 100644 index 00000000000..44a9b55a8a6 --- /dev/null +++ b/app/models/award_emoji.rb @@ -0,0 +1,35 @@ +class AwardEmoji < ActiveRecord::Base + DOWNVOTE_NAME = "thumbsdown".freeze + UPVOTE_NAME = "thumbsup".freeze + + include Participable + + belongs_to :awardable, polymorphic: true + belongs_to :user + + validates :awardable, :user, presence: true + validates :name, presence: true, inclusion: { in: Emoji.emojis_names } + validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] } + + participant :user + + scope :downvotes, -> { where(name: DOWNVOTE_NAME) } + scope :upvotes, -> { where(name: UPVOTE_NAME) } + + def downvote? + self.name == DOWNVOTE_NAME + end + + def upvote? + self.name == UPVOTE_NAME + end + + def to_note_json + { + valid: valid?, + award: true, + id: id, + name: name + } + end +end diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb new file mode 100644 index 00000000000..b4e3e9eb3dd --- /dev/null +++ b/app/models/concerns/awardable.rb @@ -0,0 +1,81 @@ +module Awardable + extend ActiveSupport::Concern + + included do + has_many :award_emoji, as: :awardable, dependent: :destroy + + if self < Participable + participant :award_emoji + end + end + + module ClassMethods + def order_upvotes_desc + order_votes_desc(AwardEmoji::UPVOTE_NAME) + end + + def order_downvotes_desc + order_votes_desc(AwardEmoji::DOWNVOTE_NAME) + end + + def order_votes_desc(emoji_name) + 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 + + joins(join_clause).group(awardable_table[:id]).reorder("COUNT(award_emoji.id) DESC") + end + end + + def grouped_awards(with_thumbs = true) + awards = award_emoji.group_by(&:name) + + if with_thumbs + awards[AwardEmoji::UPVOTE_NAME] ||= AwardEmoji.none + awards[AwardEmoji::DOWNVOTE_NAME] ||= AwardEmoji.none + end + + awards + end + + def downvotes + award_emoji.where(name: AwardEmoji::DOWNVOTE_NAME).count + end + + def upvotes + award_emoji.where(name: AwardEmoji::UPVOTE_NAME).count + end + + def emoji_awardable? + true + end + + 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? + + award_emoji.create(name: name, user: current_user) + end + + def remove_award_emoji(name, current_user) + award_emoji.where(name: name, user: current_user).destroy_all + 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 +end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index afa2ca039ae..6af76c97cd3 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -10,6 +10,7 @@ module Issuable include Mentionable include Subscribable include StripAttribute + include Awardable included do belongs_to :author, class_name: "User" @@ -99,29 +100,6 @@ module Issuable order_by(method) end end - - def order_downvotes_desc - order_votes_desc('thumbsdown') - end - - def order_upvotes_desc - order_votes_desc('thumbsup') - end - - def order_votes_desc(award_emoji_name) - issuable_table = self.arel_table - note_table = Note.arel_table - - join_clause = issuable_table.join(note_table, Arel::Nodes::OuterJoin).on( - note_table[:noteable_id].eq(issuable_table[:id]).and( - note_table[:noteable_type].eq(self.name).and( - note_table[:is_award].eq(true).and(note_table[:note].eq(award_emoji_name)) - ) - ) - ).join_sources - - joins(join_clause).group(issuable_table[:id]).reorder("COUNT(notes.id) DESC") - end end def today? @@ -144,14 +122,6 @@ module Issuable opened? || reopened? end - def downvotes - notes.awards.where(note: "thumbsdown").count - end - - def upvotes - notes.awards.where(note: "thumbsup").count - end - def subscribed_without_subscriptions?(user) participants(user).include?(user) end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index e410febdfff..2cb3e8b0176 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -36,6 +36,7 @@ class MergeRequest < ActiveRecord::Base include Referable include Sortable include Taskable + include Awardable belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" diff --git a/app/models/note.rb b/app/models/note.rb index 87ced65c650..b992b2e76f0 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -16,7 +16,6 @@ # system :boolean default(FALSE), not null # st_diff :text # updated_by_id :integer -# is_award :boolean default(FALSE), not null # require 'carrierwave/orm/activerecord' @@ -43,12 +42,9 @@ class Note < ActiveRecord::Base delegate :name, to: :project, prefix: true delegate :name, :email, to: :author, prefix: true - before_validation :set_award! before_validation :clear_blank_line_code! validates :note, :project, presence: true - validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award } - validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award } validates :line_code, line_code: true, allow_blank: true # Attachments are deprecated and are handled by Markdown uploader validates :attachment, file_size: { maximum: :max_attachment_size } @@ -60,8 +56,6 @@ class Note < ActiveRecord::Base mount_uploader :attachment, AttachmentUploader # Scopes - scope :awards, ->{ where(is_award: true) } - scope :nonawards, ->{ where(is_award: false) } scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } scope :inline, ->{ where("line_code IS NOT NULL") } scope :not_inline, ->{ where(line_code: nil) } @@ -119,19 +113,6 @@ class Note < ActiveRecord::Base where(table[:note].matches(pattern)) end - - def grouped_awards - notes = {} - - awards.select(:note).distinct.map do |note| - notes[note.note] = where(note: note.note) - end - - notes["thumbsup"] ||= Note.none - notes["thumbsdown"] ||= Note.none - - notes - end end def cross_reference? @@ -347,37 +328,25 @@ class Note < ActiveRecord::Base Event.reset_event_cache_for(self) end - def downvote? - is_award && note == "thumbsdown" - end - - def upvote? - is_award && note == "thumbsup" + def system? + read_attribute(:system) end def editable? - !system? && !is_award + !system? end def cross_reference_not_visible_for?(user) cross_reference? && referenced_mentionables(user).empty? end - # Checks if note is an award added as a comment - # - # If note is an award, this method sets is_award to true - # and changes content of the note to award name. - # - # Method is executed as a before_validation callback. - # - def set_award! - return unless awards_supported? && contains_emoji_only? - - self.is_award = true - self.note = award_emoji_name + def award_emoji? + award_emoji_supported? && contains_emoji_only? end - private + def create_award_emoji + self.noteable.award_emoji(award_emoji_name, author) + end def clear_blank_line_code! self.line_code = nil if self.line_code.blank? @@ -389,8 +358,8 @@ class Note < ActiveRecord::Base diffs.find { |d| d.new_path == self.diff.new_path } end - def awards_supported? - (for_issue? || for_merge_request?) && !for_diff_line? + def award_emoji_supported? + noteable.is_a?(Awardable) && !for_diff_line? end def contains_emoji_only? @@ -399,6 +368,6 @@ class Note < ActiveRecord::Base def award_emoji_name original_name = note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1] - AwardEmoji.normilize_emoji_name(original_name) + Gitlab::AwardEmoji.normilize_emoji_name(original_name) end end diff --git a/app/models/user.rb b/app/models/user.rb index 031315debd7..52f2904f450 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -144,6 +144,7 @@ class User < ActiveRecord::Base has_many :builds, dependent: :nullify, class_name: 'Ci::Build' has_many :todos, dependent: :destroy has_many :notification_settings, dependent: :destroy + has_many :award_emoji, as: :awardable, dependent: :destroy # # Validations |