Commit 249c6841 authored by Rajendra Kadam's avatar Rajendra Kadam Committed by Peter Leitzen

parent 6c39d8d1

author Rajendra Kadam <rajendrakadam249@gmail.com> 1580653953 +0530
committer Rajendra Kadam <rajendrakadam249@gmail.com> 1586670416 +0530

parent 6c39d8d1
author Rajendra Kadam <rajendrakadam249@gmail.com> 1580653953 +0530
committer Rajendra Kadam <rajendrakadam249@gmail.com> 1586670412 +0530

parent 6c39d8d1
author Rajendra Kadam <rajendrakadam249@gmail.com> 1580653953 +0530
committer Rajendra Kadam <rajendrakadam249@gmail.com> 1586670402 +0530

parent 6c39d8d1
author Rajendra Kadam <rajendrakadam249@gmail.com> 1580653953 +0530
committer Rajendra Kadam <rajendrakadam249@gmail.com> 1586670397 +0530

parent 6c39d8d1
author Rajendra Kadam <rajendrakadam249@gmail.com> 1580653953 +0530
committer Rajendra Kadam <rajendrakadam249@gmail.com> 1586670392 +0530

Add custom emoji schema and model spec

Add custom emoji factory for specs

Add migration file

Add custom emoji model spec

update emoji specs

Fix failures in model

Remove index creation using concurrent algorithm

Change db/schema.rb

Revert "Change db/schema.rb"

This reverts commit a5d492f738b839b165dd7e3fff5f02bedb9aabab.
parent 6fc5c01e
# 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 ...@@ -32,6 +32,7 @@ class Namespace < ApplicationRecord
belongs_to :parent, class_name: "Namespace" belongs_to :parent, class_name: "Namespace"
has_many :children, class_name: "Namespace", foreign_key: :parent_id 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 :chat_team, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :root_storage_statistics, class_name: 'Namespace::RootStorageStatistics' has_one :root_storage_statistics, class_name: 'Namespace::RootStorageStatistics'
has_one :aggregation_schedule, class_name: 'Namespace::AggregationSchedule' 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 @@ ...@@ -11,6 +11,7 @@
# #
ActiveSupport::Inflector.inflections do |inflect| ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w( inflect.uncountable %w(
custom_emoji
award_emoji award_emoji
container_repository_registry container_repository_registry
design_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 ...@@ -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; 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 ( CREATE TABLE public.dependency_proxy_blobs (
id integer NOT NULL, id integer NOT NULL,
group_id integer NOT NULL, group_id integer NOT NULL,
...@@ -16393,6 +16413,8 @@ ALTER TABLE ONLY public.container_repositories ALTER COLUMN id SET DEFAULT nextv ...@@ -16393,6 +16413,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.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_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); ALTER TABLE ONLY public.dependency_proxy_group_settings ALTER COLUMN id SET DEFAULT nextval('public.dependency_proxy_group_settings_id_seq'::regclass);
...@@ -17348,6 +17370,9 @@ ALTER TABLE ONLY public.container_repositories ...@@ -17348,6 +17370,9 @@ ALTER TABLE ONLY public.container_repositories
ALTER TABLE ONLY public.conversational_development_index_metrics ALTER TABLE ONLY public.conversational_development_index_metrics
ADD CONSTRAINT conversational_development_index_metrics_pkey PRIMARY KEY (id); 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 ALTER TABLE ONLY public.dependency_proxy_blobs
ADD CONSTRAINT dependency_proxy_blobs_pkey PRIMARY KEY (id); ADD CONSTRAINT dependency_proxy_blobs_pkey PRIMARY KEY (id);
...@@ -18814,6 +18839,8 @@ CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON publi ...@@ -18814,6 +18839,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 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_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); 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);
...@@ -21778,6 +21805,9 @@ ALTER TABLE ONLY public.project_custom_attributes ...@@ -21778,6 +21805,9 @@ ALTER TABLE ONLY public.project_custom_attributes
ALTER TABLE ONLY public.slack_integrations ALTER TABLE ONLY public.slack_integrations
ADD CONSTRAINT fk_rails_73db19721a FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE; 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 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; ADD CONSTRAINT fk_rails_74a00a1787 FOREIGN KEY (merge_request_context_commit_id) REFERENCES public.merge_request_context_commits(id) ON DELETE CASCADE;
...@@ -23073,6 +23103,7 @@ COPY "schema_migrations" (version) FROM STDIN; ...@@ -23073,6 +23103,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200227164113 20200227164113
20200227165129 20200227165129
20200228160542 20200228160542
20200229171700
20200302142052 20200302142052
20200302152516 20200302152516
20200303055348 20200303055348
......
...@@ -44,6 +44,10 @@ module Gitlab ...@@ -44,6 +44,10 @@ module Gitlab
"<img class='emoji' title=':#{name}:' alt=':#{name}:' src='#{src}' height='20' width='20' align='absmiddle' />" "<img class='emoji' title=':#{name}:' alt=':#{name}:' src='#{src}' height='20' width='20' align='absmiddle' />"
end end
def emoji_exists?(name)
emojis.has_key?(name)
end
# CSS sprite fallback takes precedence over image fallback # CSS sprite fallback takes precedence over image fallback
def gl_emoji_tag(name, options = {}) def gl_emoji_tag(name, options = {})
emoji_name = emojis_aliases[name] || name emoji_name = emojis_aliases[name] || name
......
...@@ -476,6 +476,9 @@ msgstr "" ...@@ -476,6 +476,9 @@ msgstr ""
msgid "%{name} found %{resultsString}" msgid "%{name} found %{resultsString}"
msgstr "" msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
msgid "%{name} is scheduled for %{action}" msgid "%{name} is scheduled for %{action}"
msgstr "" 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 ...@@ -95,6 +95,20 @@ RSpec.describe Gitlab::Emoji do
end end
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 describe '.gl_emoji_tag' do
it 'returns gl emoji tag if emoji is found' do it 'returns gl emoji tag if emoji is found' do
gl_tag = described_class.gl_emoji_tag('small_airplane') 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 ...@@ -17,6 +17,7 @@ RSpec.describe Namespace do
it { is_expected.to have_many :children } it { is_expected.to have_many :children }
it { is_expected.to have_one :root_storage_statistics } it { is_expected.to have_one :root_storage_statistics }
it { is_expected.to have_one :aggregation_schedule } it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_many :custom_emoji }
end end
describe 'validations' do 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