Commit cba2c203 authored by Toon Claes's avatar Toon Claes

Add scope to CustomEmoji to find emoji for resource

Award Emoji can be awarded on many things and it can be difficult to
determine which namespace the awardable belongs to.

Thus to centralize the logic that finds the custom emoji for an
awardable, we introduce a scope on the CustomEmoji model that accepts a
resource (being either a Project or a Group), determines it's root
namespace, and finds all CustomEmoji for it. In combination with the
previous commit, all the Awardable models respond to #resource_parent,
which can be provided to this new scope.

This change fixes award emoji on merge requests, epics, and issues in
nested groups.

Changelog: fixed
parent 69e73b0f
......@@ -19,6 +19,8 @@ class AwardEmoji < ApplicationRecord
participant :user
delegate :resource_parent, to: :awardable, allow_nil: true
scope :downvotes, -> { named(DOWNVOTE_NAME) }
scope :upvotes, -> { named(UPVOTE_NAME) }
scope :named, -> (names) { where(name: names) }
......@@ -63,7 +65,7 @@ class AwardEmoji < ApplicationRecord
def url
return if TanukiEmoji.find_by_alpha_code(name)
awardable.try(:namespace)&.custom_emoji&.by_name(name)&.first&.url
CustomEmoji.for_resource(resource_parent).by_name(name).select(:url).first&.url
end
def expire_cache
......
......@@ -28,6 +28,19 @@ class CustomEmoji < ApplicationRecord
alias_attribute :url, :file # this might need a change in https://gitlab.com/gitlab-org/gitlab/-/issues/230467
# Find custom emoji for the given resource.
# A resource can be either a Project or a Group, or anything responding to #root_ancestor.
# Usually it's the return value of #resource_parent on any model.
scope :for_resource, -> (resource) do
return none if resource.nil?
namespace = resource.root_ancestor
return none if namespace.nil?
namespace.custom_emoji
end
private
def valid_emoji_name
......
......@@ -24,11 +24,9 @@ module Gitlab
end
def valid_custom_emoji?(record, value)
namespace = record.try(:awardable).try(:namespace)
resource = record.try(:resource_parent)
return unless namespace
namespace.custom_emoji&.by_name(value.to_s)&.any?
CustomEmoji.for_resource(resource).by_name(value.to_s).any?
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AwardEmoji do
describe 'validations' do
context 'custom emoji' do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:emoji) { create(:custom_emoji, name: 'partyparrot', namespace: group) }
before do
group.add_maintainer(user)
end
it 'accepts custom emoji on epic' do
epic = create(:epic, group: group)
new_award = build(:award_emoji, user: user, awardable: epic, name: emoji.name)
expect(new_award).to be_valid
end
it 'accepts custom emoji on subgroup epic' do
subgroup = create(:group, parent: group)
epic = create(:epic, group: subgroup)
new_award = build(:award_emoji, user: user, awardable: epic, name: emoji.name)
expect(new_award).to be_valid
end
end
end
end
......@@ -59,17 +59,41 @@ RSpec.describe AwardEmoji do
end
end
it 'accepts custom emoji' do
user = create(:user)
group = create(:group)
group.add_maintainer(user)
context 'custom emoji' do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:emoji) { create(:custom_emoji, name: 'partyparrot', namespace: group) }
project = create(:project, namespace: group)
issue = create(:issue, project: project)
emoji = create(:custom_emoji, name: 'partyparrot', namespace: group)
new_award = build(:award_emoji, user: user, awardable: issue, name: emoji.name)
before do
group.add_maintainer(user)
end
%i[issue merge_request note_on_issue snippet].each do |awardable_type|
let_it_be(:project) { create(:project, namespace: group) }
let(:awardable) { create(awardable_type, project: project) }
it "is accepted on #{awardable_type}" do
new_award = build(:award_emoji, user: user, awardable: awardable, name: emoji.name)
expect(new_award).to be_valid
end
end
expect(new_award).to be_valid
it 'is accepted on subgroup issue' do
subgroup = create(:group, parent: group)
project = create(:project, namespace: subgroup)
issue = create(:issue, project: project)
new_award = build(:award_emoji, user: user, awardable: issue, name: emoji.name)
expect(new_award).to be_valid
end
it 'is not supported on personal snippet (yet)' do
snippet = create(:personal_snippet)
new_award = build(:award_emoji, user: snippet.author, awardable: snippet, name: 'null')
expect(new_award).not_to be_valid
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment