mirror of
https://github.com/mastodon/mastodon.git
synced 2026-03-21 18:05:23 -05:00
Use normalizes for tag name attribute (#37119)
This commit is contained in:
parent
e92b7beb75
commit
9762b4a75c
|
|
@ -39,6 +39,6 @@ class Api::V1::TagsController < Api::BaseController
|
|||
def set_or_create_tag
|
||||
return not_found unless Tag::HASHTAG_NAME_RE.match?(params[:id])
|
||||
|
||||
@tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id])
|
||||
@tag = Tag.find_normalized(params[:id]) || Tag.new(name: params[:id], display_name: params[:id])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class FeaturedTag < ApplicationRecord
|
|||
|
||||
normalizes :name, with: ->(name) { name.strip.delete_prefix('#') }
|
||||
|
||||
scope :by_name, ->(name) { joins(:tag).where(tag: { name: HashtagNormalizer.new.normalize(name) }) }
|
||||
scope :by_name, ->(name) { joins(:tag).where(tag: { name: }) }
|
||||
|
||||
before_validation :set_tag
|
||||
|
||||
|
|
|
|||
|
|
@ -65,8 +65,9 @@ class Tag < ApplicationRecord
|
|||
.where(statuses: { id: account.statuses.select(:id).limit(RECENT_STATUS_LIMIT) })
|
||||
.group(:id).order(Arel.star.count.desc)
|
||||
}
|
||||
scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index
|
||||
scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(normalize_value_for(:name, term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index
|
||||
|
||||
normalizes :name, with: ->(value) { HashtagNormalizer.new.normalize(value) }
|
||||
normalizes :display_name, with: ->(value) { value.gsub(HASHTAG_INVALID_CHARS_RE, '') }
|
||||
|
||||
update_index('tags', :self)
|
||||
|
|
@ -111,13 +112,13 @@ class Tag < ApplicationRecord
|
|||
|
||||
class << self
|
||||
def find_or_create_by_names(name_or_names)
|
||||
names = Array(name_or_names).map { |str| [normalize(str), str] }.uniq(&:first)
|
||||
names = Array(name_or_names).map { |str| [normalize_value_for(:name, str), str] }.uniq(&:first)
|
||||
|
||||
names.map do |(normalized_name, display_name)|
|
||||
names.map do |name, display_name|
|
||||
tag = begin
|
||||
matching_name(normalized_name).first || create!(name: normalized_name, display_name:)
|
||||
matching_name(name).first || create!(name:, display_name:)
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
find_normalized(normalized_name)
|
||||
find_normalized(name)
|
||||
end
|
||||
|
||||
yield tag if block_given?
|
||||
|
|
@ -148,7 +149,7 @@ class Tag < ApplicationRecord
|
|||
end
|
||||
|
||||
def matching_name(name_or_names)
|
||||
names = Array(name_or_names).map { |name| arel_table.lower(normalize(name)) }
|
||||
names = Array(name_or_names).map { |name| arel_table.lower(normalize_value_for(:name, name)) }
|
||||
|
||||
if names.size == 1
|
||||
where(arel_table[:name].lower.eq(names.first))
|
||||
|
|
@ -156,10 +157,6 @@ class Tag < ApplicationRecord
|
|||
where(arel_table[:name].lower.in(names))
|
||||
end
|
||||
end
|
||||
|
||||
def normalize(str)
|
||||
HashtagNormalizer.new.normalize(str)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -173,6 +170,6 @@ class Tag < ApplicationRecord
|
|||
end
|
||||
|
||||
def display_name_matches_name?
|
||||
HashtagNormalizer.new.normalize(display_name).casecmp(name).zero?
|
||||
self.class.normalize_value_for(:name, display_name).casecmp(name).zero?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class TagSearchService < BaseService
|
|||
def ensure_exact_match(results)
|
||||
return results unless @offset.nil? || @offset.zero?
|
||||
|
||||
normalized_query = Tag.normalize(@query)
|
||||
normalized_query = Tag.normalize_value_for(:name, @query)
|
||||
exact_match = results.find { |tag| tag.name.downcase == normalized_query }
|
||||
exact_match ||= Tag.find_normalized(normalized_query)
|
||||
unless exact_match.nil?
|
||||
|
|
|
|||
|
|
@ -40,26 +40,40 @@ RSpec.describe Tag do
|
|||
I18n.t('tags.does_not_match_previous_name')
|
||||
end
|
||||
|
||||
it 'invalid with #' do
|
||||
expect(described_class.new(name: '#hello_world')).to_not be_valid
|
||||
describe 'when skipping normalizations' do
|
||||
subject { described_class.new }
|
||||
|
||||
before { subject.attributes[:name] = name }
|
||||
|
||||
context 'with a # in string' do
|
||||
let(:name) { '#hello_world' }
|
||||
|
||||
it { is_expected.to_not be_valid }
|
||||
end
|
||||
|
||||
context 'with a . in string' do
|
||||
let(:name) { '.abcdef123' }
|
||||
|
||||
it { is_expected.to_not be_valid }
|
||||
end
|
||||
|
||||
context 'with a space in string' do
|
||||
let(:name) { 'hello world' }
|
||||
|
||||
it { is_expected.to_not be_valid }
|
||||
end
|
||||
end
|
||||
|
||||
it 'invalid with .' do
|
||||
expect(described_class.new(name: '.abcdef123')).to_not be_valid
|
||||
end
|
||||
|
||||
it 'invalid with spaces' do
|
||||
expect(described_class.new(name: 'hello world')).to_not be_valid
|
||||
end
|
||||
|
||||
it 'valid with aesthetic' do
|
||||
expect(described_class.new(name: 'aesthetic')).to be_valid
|
||||
end
|
||||
it { is_expected.to allow_value('aesthetic').for(:name) }
|
||||
end
|
||||
|
||||
describe 'Normalizations' do
|
||||
it { is_expected.to normalize(:display_name).from('#HelloWorld').to('HelloWorld') }
|
||||
it { is_expected.to normalize(:display_name).from('Hello❤️World').to('HelloWorld') }
|
||||
|
||||
it { is_expected.to normalize(:name).from('#hello_world').to('hello_world') }
|
||||
it { is_expected.to normalize(:name).from('hello world').to('helloworld') }
|
||||
it { is_expected.to normalize(:name).from('.abcdef123').to('abcdef123') }
|
||||
end
|
||||
|
||||
describe 'HASHTAG_RE' do
|
||||
|
|
@ -210,7 +224,7 @@ RSpec.describe Tag do
|
|||
upcase_string = 'abcABCabcABCやゆよ'
|
||||
downcase_string = 'abcabcabcabcやゆよ'
|
||||
|
||||
tag = Fabricate(:tag, name: HashtagNormalizer.new.normalize(downcase_string))
|
||||
tag = Fabricate(:tag, name: downcase_string)
|
||||
expect(described_class.find_normalized(upcase_string)).to eq tag
|
||||
end
|
||||
end
|
||||
|
|
@ -239,7 +253,7 @@ RSpec.describe Tag do
|
|||
upcase_string = 'abcABCabcABCやゆよ'
|
||||
downcase_string = 'abcabcabcabcやゆよ'
|
||||
|
||||
tag = Fabricate(:tag, name: HashtagNormalizer.new.normalize(downcase_string))
|
||||
tag = Fabricate(:tag, name: downcase_string)
|
||||
expect(described_class.matches_name(upcase_string)).to eq [tag]
|
||||
end
|
||||
|
||||
|
|
@ -254,7 +268,7 @@ RSpec.describe Tag do
|
|||
upcase_string = 'abcABCabcABCやゆよ'
|
||||
downcase_string = 'abcabcabcabcやゆよ'
|
||||
|
||||
tag = Fabricate(:tag, name: HashtagNormalizer.new.normalize(downcase_string))
|
||||
tag = Fabricate(:tag, name: downcase_string)
|
||||
expect(described_class.matching_name(upcase_string)).to eq [tag]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user