このコミットが含まれているのは:
@@ -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, 'ニジラーと紐づいてゐるタグはニジラー・カテゴリである必要があります.'
|
||||
|
||||
@@ -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
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする