Commit 4addd43e authored by Peter Leitzen's avatar Peter Leitzen

Merge branch 'emoji-api-model' into 'master'

Add custom emoji model and database table

See merge request gitlab-org/gitlab!24229
parents 999c81c7 249c6841
# frozen_string_literal: true
class CustomEmoji < ApplicationRecord
belongs_to :namespace, inverse_of: :custom_emoji
validate :valid_emoji_name
validates :namespace, presence: true
validates :name,
uniqueness: { scope: [:namespace_id, :name] },
presence: true,
length: { maximum: 36 },
format: { with: /\A\w+\z/ }
private
def valid_emoji_name
if Gitlab::Emoji.emoji_exists?(name)
errors.add(:name, _('%{name} is already being used for another emoji') % { name: self.name })
end
end
end
......@@ -32,6 +32,7 @@ class Namespace < ApplicationRecord
belongs_to :parent, class_name: "Namespace"
has_many :children, class_name: "Namespace", foreign_key: :parent_id
has_many :custom_emoji, inverse_of: :namespace
has_one :chat_team, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :root_storage_statistics, class_name: 'Namespace::RootStorageStatistics'
has_one :aggregation_schedule, class_name: 'Namespace::AggregationSchedule'
......
---
title: Add custom emoji model and database table
merge_request: 24229
author: Rajendra Kadam
type: added
......@@ -11,6 +11,7 @@
#
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w(
custom_emoji
award_emoji
container_repository_registry
design_registry
......
class CreateCustomEmojis < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:custom_emoji)
create_table :custom_emoji do |t|
t.references :namespace, index: false, null: false, foreign_key: { on_delete: :cascade }
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :updated_at, null: false
t.text :name, null: false
t.text :file, null: false
end
end
unless index_exists?(:custom_emoji, [:namespace_id, :name], unique: true)
add_index :custom_emoji, [:namespace_id, :name], unique: true
end
add_text_limit(:custom_emoji, :name, 36)
add_text_limit(:custom_emoji, :file, 255)
end
def down
drop_table :custom_emoji
end
end
......@@ -10818,6 +10818,26 @@ CREATE SEQUENCE public.conversational_development_index_metrics_id_seq
ALTER SEQUENCE public.conversational_development_index_metrics_id_seq OWNED BY public.conversational_development_index_metrics.id;
CREATE TABLE public.custom_emoji (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
name text NOT NULL,
file text NOT NULL,
CONSTRAINT check_8c586dd507 CHECK ((char_length(name) <= 36)),
CONSTRAINT check_dd5d60f1fb CHECK ((char_length(file) <= 255))
);
CREATE SEQUENCE public.custom_emoji_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE public.custom_emoji_id_seq OWNED BY public.custom_emoji.id;
CREATE TABLE public.dependency_proxy_blobs (
id integer NOT NULL,
group_id integer NOT NULL,
......@@ -16394,6 +16414,8 @@ ALTER TABLE ONLY public.container_repositories ALTER COLUMN id SET DEFAULT nextv
ALTER TABLE ONLY public.conversational_development_index_metrics ALTER COLUMN id SET DEFAULT nextval('public.conversational_development_index_metrics_id_seq'::regclass);
ALTER TABLE ONLY public.custom_emoji ALTER COLUMN id SET DEFAULT nextval('public.custom_emoji_id_seq'::regclass);
ALTER TABLE ONLY public.dependency_proxy_blobs ALTER COLUMN id SET DEFAULT nextval('public.dependency_proxy_blobs_id_seq'::regclass);
ALTER TABLE ONLY public.dependency_proxy_group_settings ALTER COLUMN id SET DEFAULT nextval('public.dependency_proxy_group_settings_id_seq'::regclass);
......@@ -17349,6 +17371,9 @@ ALTER TABLE ONLY public.container_repositories
ALTER TABLE ONLY public.conversational_development_index_metrics
ADD CONSTRAINT conversational_development_index_metrics_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.custom_emoji
ADD CONSTRAINT custom_emoji_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.dependency_proxy_blobs
ADD CONSTRAINT dependency_proxy_blobs_pkey PRIMARY KEY (id);
......@@ -18815,6 +18840,8 @@ CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON publi
CREATE INDEX index_container_repository_on_name_trigram ON public.container_repositories USING gin (name public.gin_trgm_ops);
CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON public.custom_emoji USING btree (namespace_id, name);
CREATE UNIQUE INDEX index_daily_build_group_report_results_unique_columns ON public.ci_daily_build_group_report_results USING btree (project_id, ref_path, date, group_name);
CREATE UNIQUE INDEX index_daily_report_results_unique_columns ON public.ci_daily_report_results USING btree (project_id, ref_path, param_type, date, title);
......@@ -21779,6 +21806,9 @@ ALTER TABLE ONLY public.project_custom_attributes
ALTER TABLE ONLY public.slack_integrations
ADD CONSTRAINT fk_rails_73db19721a FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.custom_emoji
ADD CONSTRAINT fk_rails_745925b412 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.merge_request_context_commit_diff_files
ADD CONSTRAINT fk_rails_74a00a1787 FOREIGN KEY (merge_request_context_commit_id) REFERENCES public.merge_request_context_commits(id) ON DELETE CASCADE;
......@@ -23074,6 +23104,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200227164113
20200227165129
20200228160542
20200229171700
20200302142052
20200302152516
20200303055348
......
......@@ -44,6 +44,10 @@ module Gitlab
"<img class='emoji' title=':#{name}:' alt=':#{name}:' src='#{src}' height='20' width='20' align='absmiddle' />"
end
def emoji_exists?(name)
emojis.has_key?(name)
end
# CSS sprite fallback takes precedence over image fallback
def gl_emoji_tag(name, options = {})
emoji_name = emojis_aliases[name] || name
......
......@@ -476,6 +476,9 @@ msgstr ""
msgid "%{name} found %{resultsString}"
msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
msgid "%{name} is scheduled for %{action}"
msgstr ""
......
# frozen_string_literal: true
FactoryBot.define do
factory :custom_emoji, class: 'CustomEmoji' do
sequence(:name) { |n| "custom_emoji#{n}" }
namespace
file { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png')) }
end
end
......@@ -95,6 +95,20 @@ RSpec.describe Gitlab::Emoji do
end
end
describe '.emoji_exists?' do
it 'returns true if the name exists' do
emoji_exists = described_class.emoji_exists?('100')
expect(emoji_exists).to be_truthy
end
it 'returns false if the name does not exist' do
emoji_exists = described_class.emoji_exists?('random')
expect(emoji_exists).to be_falsey
end
end
describe '.gl_emoji_tag' do
it 'returns gl emoji tag if emoji is found' do
gl_tag = described_class.gl_emoji_tag('small_airplane')
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe CustomEmoji do
describe 'Associations' do
it { is_expected.to belong_to(:namespace) }
it { is_expected.to have_db_column(:file) }
it { is_expected.to validate_length_of(:name).is_at_most(36) }
it { is_expected.to validate_presence_of(:name) }
end
describe 'exclusion of duplicated emoji' do
let(:emoji_name) { Gitlab::Emoji.emojis_names.sample }
it 'disallows emoji names of built-in emoji' do
new_emoji = build(:custom_emoji, name: emoji_name)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to eq(name: ["#{emoji_name} is already being used for another emoji"])
end
it 'disallows duplicate custom emoji names within namespace' do
old_emoji = create(:custom_emoji)
new_emoji = build(:custom_emoji, name: old_emoji.name, namespace: old_emoji.namespace)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to eq(name: ["has already been taken"])
end
end
end
......@@ -17,6 +17,7 @@ RSpec.describe Namespace do
it { is_expected.to have_many :children }
it { is_expected.to have_one :root_storage_statistics }
it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_many :custom_emoji }
end
describe 'validations' do
......
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