このコミットが含まれているのは:
2026-09-27 03:47:27 +09:00
コミット 701830b643
18個のファイルの変更、260行の追加、187行の削除
+4 -5
ファイルの表示
@@ -135,7 +135,7 @@ class Tag < ApplicationRecord
raise SectionLiteralParseError.new(raw_name, raw_name)
end
name = TagName.canonicalise(name).first
name = TagName.canonicalise(locale, name).first
find_or_create_by_tag_name!(locale, name, category: (cat || :general)).tap do |tag|
if deny_deprecated && tag.deprecated?
@@ -235,10 +235,7 @@ class Tag < ApplicationRecord
end
tag = tn.tag
if tag
tag.update!(tag_name_id: tn.id) if tag.tag_name_id != tn.id
return tag
end
return tag if tag
tag = Tag.create!(tag_name: tn, category:)
tn.update!(tag:)
@@ -279,6 +276,8 @@ class Tag < ApplicationRecord
end
TagVersioning.record!(source_tag, event_type: :discard, created_by_user:)
source_tag.tag_names.update_all(tag_id: source_tag.id, primary_key: false,
updated_at: Time.current)
source_tag.destroy!
source_tag_name.update_columns(canonical_id: target_tag.tag_name_id,
+25 -19
ファイルの表示
@@ -1,24 +1,36 @@
class TagName < ApplicationRecord
belongs_to :language, foreign_key: :language_code, primary_key: :code
belongs_to :tag, optional: true
has_one :wiki_page
belongs_to :canonical, class_name: 'TagName', optional: true
has_many :aliases, class_name: 'TagName', foreign_key: :canonical_id
validates :name, presence: true,
length: { maximum: 255 },
uniqueness: { scope: :language_code }
validates :name, presence: true, length: { maximum: 255 }, uniqueness: true
validate :canonical_must_be_canonical
validate :alias_name_must_not_have_prefix
validate :canonical_must_not_be_present_with_tag_or_wiki_page
validate :alias_must_not_have_wiki_page
validate :name_must_be_sanitised
def self.canonicalise names
def primary? = primary_flg
def canonical = TagName.find_by(language:, tag:, primary_flg: true)
def aliases = TagName.where(language:, tag:, primary_flg: false)
def self.canonicalise locale, names
names = Array(names).map { |n| n.to_s.strip }.reject(&:blank?)
return [] if names.blank?
tns = TagName.includes(:canonical).where(name: names).index_by(&:name)
tns = TagName.where(language_code: locale.language_code, name: names).index_by(&:name)
names.map { |name| tns[name]&.canonical&.name || name }.uniq
names.map { |name|
if tns[name].primary_flg
name
else
TagName.find_by(language_code: locale.language_code,
tag_id: tns[name].tag_id,
primary_flg: true).name
end
}.uniq
end
def self.generate_name locale, tag, name
@@ -29,21 +41,15 @@ class TagName < ApplicationRecord
private
def canonical_must_be_canonical
if canonical&.canonical_id?
errors.add :canonical, 'canonical は実体を示す必要があります.'
end
end
def alias_name_must_not_have_prefix
if canonical_id? && name.to_s.include?(':')
if !(primary?) && name.to_s.include?(':')
errors.add :name, 'エーリアス名にプレフィクスを含むことはできません.'
end
end
def canonical_must_not_be_present_with_tag_or_wiki_page
if canonical_id? && (tag || wiki_page)
errors.add :canonical, 'タグもしくは Wiki の参照がある名前はエーリアスになれません.'
def alias_must_not_have_wiki_page
if !(primary?) && wiki_page
errors.add :primary_flg, 'Wiki 参照がある名前はエーリアスになれません.'
end
end
+26 -19
ファイルの表示
@@ -15,31 +15,38 @@ class TagNameSanitisationRule < ApplicationRecord
end
def apply!
TagName.find_each do |tn|
name = sanitise(tn.name)
next if name == tn.name
Language.find_each do |language|
TagName.where(language:).find_each do |tn|
name = sanitise(tn.name)
next if name == tn.name
TagName.transaction do
existing_tn = TagName.find_by(name:)
if existing_tn
existing_tn = existing_tn.canonical || existing_tn
next if existing_tn.id == tn.id
TagName.transaction do
existing_tn = TagName.find_by(language:, name:)
if existing_tn
unless existing_tn.primary_flg
existing_tn = TagName.find_by!(language:,
tag_id: existing_tn.tag_id,
primary_flg: true)
end
next if existing_tn.id == tn.id
existing_tag = Tag.find_by(tag_name_id: existing_tn.id)
source_tag = Tag.find_by(tag_name_id: tn.id)
existing_tag = existing_tn.tag
source_tag = tn.tag
if existing_tag
Tag.merge_tags!(existing_tag, source_tag) if tn.tag
elsif source_tag
source_tag.update_columns(tag_name_id: existing_tn.id, updated_at: Time.current)
if existing_tag
Tag.merge_tags!(existing_tag, source_tag) if tn.tag
elsif source_tag
source_tag.update_columns(tag_name_id: existing_tn.id, updated_at: Time.current)
existing_tn.update_columns(tag_id: source_tag.id, updated_at: Time.current)
end
tn.destroy!
next
end
tn.destroy!
next
# TagName 側の自動サニタイズを回避
tn.update_columns(name:, updated_at: Time.current)
end
# TagName 側の自動サニタイズを回避
tn.update_columns(name:, updated_at: Time.current)
end
end
end