From aa6d07dbd9c9ae20e690c88f34d3764d91ee2cef Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Mon, 8 Jan 2024 06:20:59 -0500
Subject: [PATCH] Use normalizes to prepare CustomEmoji `domain` value (#28624)

---
 app/models/custom_emoji.rb       |  6 +-----
 spec/models/custom_emoji_spec.rb | 21 ++++++++++++++++-----
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 97b1c63bf3..550f005d59 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -41,7 +41,7 @@ class CustomEmoji < ApplicationRecord
 
   has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' } }, validate_media_type: false
 
-  before_validation :downcase_domain
+  normalizes :domain, with: ->(domain) { domain.downcase }
 
   validates_attachment :image, content_type: { content_type: IMAGE_MIME_TYPES }, presence: true, size: { less_than: LIMIT }
   validates :shortcode, uniqueness: { scope: :domain }, format: { with: SHORTCODE_ONLY_RE }, length: { minimum: 2 }
@@ -95,8 +95,4 @@ class CustomEmoji < ApplicationRecord
   def remove_entity_cache
     Rails.cache.delete(EntityCache.instance.to_key(:emoji, shortcode, domain))
   end
-
-  def downcase_domain
-    self.domain = domain.downcase unless domain.nil?
-  end
 end
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
index 06affd634a..a0903e5978 100644
--- a/spec/models/custom_emoji_spec.rb
+++ b/spec/models/custom_emoji_spec.rb
@@ -78,12 +78,23 @@ RSpec.describe CustomEmoji do
     end
   end
 
-  describe 'pre_validation' do
-    let(:custom_emoji) { Fabricate(:custom_emoji, domain: 'wWw.MaStOdOn.CoM') }
+  describe 'Normalizations' do
+    describe 'downcase domain value' do
+      context 'with a mixed case domain value' do
+        it 'normalizes the value to downcased' do
+          custom_emoji = Fabricate.build(:custom_emoji, domain: 'wWw.MaStOdOn.CoM')
 
-    it 'downcases' do
-      custom_emoji.valid?
-      expect(custom_emoji.domain).to eq('www.mastodon.com')
+          expect(custom_emoji.domain).to eq('www.mastodon.com')
+        end
+      end
+
+      context 'with a nil domain value' do
+        it 'leaves the value as nil' do
+          custom_emoji = Fabricate.build(:custom_emoji, domain: nil)
+
+          expect(custom_emoji.domain).to be_nil
+        end
+      end
     end
   end
 end