このコミットが含まれているのは:
2026-09-27 17:13:02 +09:00
コミット 56205b7052
3個のファイルの変更、104行の追加、67行の削除
+88 -46
ファイルの表示
@@ -5,6 +5,8 @@ require 'set'
class TagsController < ApplicationController
def index
locale = resolve_locale!
post_id = params[:post]
name = params[:name].presence
@@ -36,9 +38,14 @@ class TagsController < ApplicationController
tags =
if post_id.present?
Tag.joins(:posts, :tag_name).where(posts: { id: post_id })
Tag
.joins(:posts, :tag_names)
.where(tag_names: { language_code: locale.language_code, primary_flg: true },
posts: { id: post_id })
else
Tag.joins(:tag_name)
Tag
.joins(:tag_names)
.where(tag_names: { language_code: locale.language_code, primary_flg: true })
end
external_tags =
@@ -167,9 +174,10 @@ class TagsController < ApplicationController
tags_by_id =
Tag
.joins(:tag_name)
.includes(:tag_name, :materials, tag_name: :wiki_page)
.where(id: tag_ids)
.joins(:tag_names)
.includes(:tag_names, :materials, tag_names: :wiki_page)
.where(tag_names: { language_code: locale.language.code, primary_flg: true },
id: tag_ids)
.index_by(&:id)
external_tags_by_id =
ExternalTag
@@ -205,6 +213,8 @@ class TagsController < ApplicationController
end
def autocomplete
locale = resolve_locale!
q = params[:q].to_s.strip.sub(/\Anot:/i, '')
prefix = "#{ ActiveRecord::Base.sanitize_sql_like(q) }%"
@@ -213,28 +223,28 @@ class TagsController < ApplicationController
alias_rows =
TagName
.where(language_code: locale.language_code, primary_code: false)
.where('name LIKE ?', prefix)
.where.not(canonical_id: nil)
.pluck(:canonical_id, :name)
.pluck(:tag_id, :name)
matched_alias_by_tag_name_id = { }
canonical_ids = []
alias_rows.each do |canonical_id, alias_name|
canonical_ids << canonical_id
matched_alias_by_tag_name_id[canonical_id] ||= alias_name
tag_ids = []
alias_rows.each do |tag_id, alias_name|
tag_ids << tag_id
matched_alias_by_tag_name_id[tag_id] ||= alias_name
end
base =
Tag
.joins(:tag_name)
.includes(:tag_name, :materials, tag_name: :wiki_page)
.where(deprecated_at: nil)
.joins(:tag_names)
.includes(:tag_names, :materials, tag_names: :wiki_page)
.where(tag_names: { language_code: locale.language_code, primary_flg: true },
deprecated_at: nil)
base = base.where('tags.post_count > 0') if present_only
canonical_hit = base.where('tag_names.name LIKE ?', prefix)
internal_tags = canonical_hit.or(base.where(tag_name_id: canonical_ids.uniq))
internal_tags = canonical_hit.or(base.where(id: tag_ids.uniq))
internal_rows =
internal_tags
@@ -265,11 +275,14 @@ class TagsController < ApplicationController
end
def show
locale = resolve_locale!
tag =
Tag
.joins(:tag_name)
.includes(:tag_name, :materials, tag_name: :wiki_page)
.find_by(id: params[:id])
.joins(:tag_names)
.includes(:tag_names, :materials, tag_names: :wiki_page)
.find_by(id: params[:id],
tag_names: { language_code: locale.language_code, primary_flg: true })
return render json: TagRepr.base(tag) if tag
external_tag = ExternalTag.find_by(id: params[:id])
@@ -282,11 +295,13 @@ class TagsController < ApplicationController
name = params[:name].to_s.strip
return render_bad_request('name は必須です.') if name.blank?
locale = resolve_locale!
tag =
Tag
.joins(:tag_name)
.includes(:tag_name, :materials, tag_name: :wiki_page)
.find_by(tag_names: { name: })
.joins(:tag_names)
.includes(:tag_names, :materials, tag_names: :wiki_page)
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
return render json: TagRepr.base(tag) if tag
platform, external_name = name.split(':', 2)
@@ -299,9 +314,13 @@ class TagsController < ApplicationController
end
def deerjikists
tag = Tag.joins(:tag_name)
.includes(:tag_name, tag_name: :wiki_page)
.find_by(id: params[:id])
locale = resolve_locale!
tag =
Tag.joins(:tag_names)
.includes(:tag_names, tag_names: :wiki_page)
.find_by(id: params[:id],
tag_names: { language_code: locale.language_code, primary_flg: true })
return head :not_found unless tag
render json: { tag: TagRepr.base(tag),
@@ -312,9 +331,13 @@ class TagsController < ApplicationController
name = params[:name].to_s.strip
return render_bad_request('name は必須です.') if name.blank?
tag = Tag.joins(:tag_name)
.includes(:tag_name, tag_name: :wiki_page)
.find_by(tag_names: { name: })
locale = resolve_locale!
tag =
Tag
.joins(:tag_names)
.includes(:tag_names, tag_names: :wiki_page)
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
return head :not_found unless tag
render json: { tag: TagRepr.base(tag),
@@ -325,14 +348,19 @@ class TagsController < ApplicationController
return head :unauthorized unless current_user
return head :forbidden unless current_user.gte_member?
tag = Tag.joins(:tag_name)
.includes(:tag_name, tag_name: :wiki_page)
.find_by(id: params[:id])
tag =
Tag
.joins(:tag_names)
.includes(:tag_names, tag_names: :wiki_page)
.find_by(id: params[:id],
tag_names: { language_code: locale.language_code, primary_flg: true })
return head :not_found unless tag
rows = normalise_deerjikist_rows(tag)
return if performed?
locale = resolve_locale!
ApplicationRecord.transaction do
tag.lock!
@@ -346,7 +374,7 @@ class TagsController < ApplicationController
row_indexes_by_key.key?([deerjikist.platform, deerjikist.code])
}
render_deerjikist_conflicts(requested_deerjikists, row_indexes_by_key, tag)
render_deerjikist_conflicts(locale, requested_deerjikists, row_indexes_by_key, tag)
raise ActiveRecord::Rollback if performed?
requested_keys_set = requested_keys.to_set
@@ -367,7 +395,7 @@ class TagsController < ApplicationController
render_deerjikist_form_record_invalid(deerjikist, row_index) unless deerjikist.save
rescue ActiveRecord::RecordNotUnique
conflicts = lock_deerjikists_for_tag_update(tag.id, [[platform, code]])
render_deerjikist_conflicts(conflicts, row_indexes_by_key, tag)
render_deerjikist_conflicts(locale, conflicts, row_indexes_by_key, tag)
end
raise ActiveRecord::Rollback if performed?
end
@@ -381,11 +409,16 @@ class TagsController < ApplicationController
def materials_by_name
name = params[:name].to_s.strip
return render_bad_request('name は必須です.') if name.blank?
locale = resolve_locale!
material_filter = material_filter_param(default: 'any')
tag = Tag.joins(:tag_name)
.includes(:tag_name, :materials, tag_name: :wiki_page)
.find_by(tag_names: { name: })
tag =
Tag
.joins(:tag_names)
.includes(:tag_names, :materials, tag_names: :wiki_page)
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
return head :not_found unless tag
graph = build_with_depth_graph(material_filter)
@@ -506,6 +539,8 @@ class TagsController < ApplicationController
end
def build_with_depth_graph material_filter
locale = resolve_locale!
children_by_parent_id = Hash.new { |h, k| h[k] = [] }
parent_ids_by_child_id = Hash.new { |h, k| h[k] = [] }
@@ -520,10 +555,13 @@ class TagsController < ApplicationController
material_tag_ids = Material.unscoped.kept.where.not(tag_id: nil).distinct.pluck(:tag_id).to_set
tags_by_id = Tag.joins(:tag_name)
.where(id: tag_ids)
.pluck('tags.id', 'tag_names.name', 'tags.category', 'tags.deprecated_at')
.each_with_object({ }) do |(id, name, category, deprecated_at), h|
tags_by_id =
Tag
.joins(:tag_names)
.where(id: tag_ids,
tag_names: { language_code: locale.language_code, primary_flg: true })
.pluck('tags.id', 'tag_names.name', 'tags.category', 'tags.deprecated_at')
.each_with_object({ }) do |(id, name, category, deprecated_at), h|
h[id] = { name:, category:, deprecated: deprecated_at.present?,
has_material: material_tag_ids.include?(id) }
end
@@ -857,15 +895,19 @@ class TagsController < ApplicationController
.to_a
end
def render_deerjikist_conflicts deerjikists, row_indexes_by_key, tag
def render_deerjikist_conflicts locale, deerjikists, row_indexes_by_key, tag
conflicts = deerjikists.filter { |deerjikist| deerjikist.tag_id != tag.id }
return if conflicts.empty?
tag_names_by_id = Tag
.joins(:tag_name)
.where(id: conflicts.map(&:tag_id).uniq)
.pluck('tags.id', 'tag_names.name')
.to_h
locale = resolve_locale!
tag_names_by_id =
Tag
.joins(:tag_names)
.where(tag_names: { language_code: locale.language_code, primary_flg: true },
id: conflicts.map(&:tag_id).uniq)
.pluck('tags.id', 'tag_names.name')
.to_h
fields = { }
conflicts.each do |deerjikist|
+9 -21
ファイルの表示
@@ -51,12 +51,9 @@ class Tag < ApplicationRecord
has_many :tag_versions
has_many :tag_names
delegate :wiki_page, to: :tag_name
attribute :version_no, :integer, default: 1
validates :tag_name, presence: true
enum :category, deerjikist: 'deerjikist',
meme: 'meme',
character: 'character',
@@ -66,8 +63,6 @@ class Tag < ApplicationRecord
validates :category, presence: true, inclusion: { in: Tag.categories.keys }
validate :tag_name_mustnt_start_with_nico
validate :tag_name_must_be_canonical
validate :category_must_be_deerjikist_with_deerjikists
CATEGORY_PREFIXES = {
@@ -84,6 +79,7 @@ class Tag < ApplicationRecord
def tag_name(language_code) = tag_names.find_by(language_code:, primary_flg: true)
def name(language_code) = tag_name(language_code)&.name
def wiki_page = WikiPage.find_by(tag_name_id: id)
def deprecated? = deprecated_at?
@@ -234,7 +230,7 @@ class Tag < ApplicationRecord
tag = tn.tag
return tag if tag
tag = Tag.create!(tag_name: tn, category:)
tag = Tag.create!(tag_name_id: tn.id, category:)
tn.update!(tag:)
tag
@@ -295,28 +291,20 @@ class Tag < ApplicationRecord
target_tag.reload
end
def snapshot_aliases = tag_name.aliases.order(:name).pluck(:name)
def snapshot_aliases(language_code) = tag_name(language_code).aliases.order(:name).pluck(:name)
def snapshot_parent_tag_ids = parents.order(:id).pluck(:id)
def snapshot_linked_tag_names
linked_tags.joins(:tag_name).order('tag_names.name').pluck('tag_names.name')
def snapshot_linked_tag_names language_code
linked_tags
.joins(:tag_names)
.where(tag_names: { language_code:, primary_flg: true })
.order('tag_names.name')
.pluck('tag_names.name')
end
private
def tag_name_mustnt_start_with_nico
if name.to_s.downcase.start_with?('nico:')
errors.add :name, 'タグの命名規則に反してゐます.'
end
end
def tag_name_must_be_canonical
if tag_name&.canonical_id?
errors.add :tag_name, 'tag_names へは実体を示す必要があります.'
end
end
def category_must_be_deerjikist_with_deerjikists
if !(deerjikist?) && deerjikists.exists?
errors.add :category, 'ニジラーと紐づいてゐるタグはニジラー・カテゴリである必要があります.'
+7
ファイルの表示
@@ -10,6 +10,7 @@ class TagName < ApplicationRecord
validate :alias_name_must_not_have_prefix
validate :alias_must_not_have_wiki_page
validate :name_must_be_sanitised
validate :name_mustnt_start_with_nico
def primary? = primary_flg
@@ -58,4 +59,10 @@ class TagName < ApplicationRecord
errors.add :name, '名前に使用できない文字が含まれてゐます.'
end
end
def name_mustnt_start_with_nico
if name.to_s.downcase.start_with?('nico:')
errors.add :name, 'タグの命名規則に反してゐます.'
end
end
end