このコミットが含まれているのは:
@@ -133,12 +133,14 @@ class MaterialsController < ApplicationController
|
|||||||
block = MaterialImportBlockMatcher.match_for_sha256(file_sha256)
|
block = MaterialImportBlockMatcher.match_for_sha256(file_sha256)
|
||||||
return render_material_import_block(block) if block
|
return render_material_import_block(block) if block
|
||||||
|
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
uploaded_blob = build_uploaded_material_blob!(file, file_sha256)
|
uploaded_blob = build_uploaded_material_blob!(file, file_sha256)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Material.transaction do
|
Material.transaction do
|
||||||
MaterialVersionRecorder.ensure_snapshot!(material, created_by_user: current_user)
|
MaterialVersionRecorder.ensure_snapshot!(material, created_by_user: current_user)
|
||||||
tag = resolve_material_tag!(tag_name_raw)
|
tag = resolve_material_tag!(locale, tag_name_raw)
|
||||||
material.assign_attributes(tag:, url:, updated_by_user: current_user)
|
material.assign_attributes(tag:, url:, updated_by_user: current_user)
|
||||||
if uploaded_blob
|
if uploaded_blob
|
||||||
material.file.attach(uploaded_blob)
|
material.file.attach(uploaded_blob)
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ class PostsController < ApplicationController
|
|||||||
preflight = PostCreatePreflight.new(
|
preflight = PostCreatePreflight.new(
|
||||||
attributes: post_create_attributes,
|
attributes: post_create_attributes,
|
||||||
thumbnail: params[:thumbnail],
|
thumbnail: params[:thumbnail],
|
||||||
host: request.base_url).run
|
host: request.base_url).run(locale)
|
||||||
return render json: dry_run_json(preflight) if bool?(:dry)
|
return render json: dry_run_json(preflight) if bool?(:dry)
|
||||||
if preflight[:existing_post_id].present?
|
if preflight[:existing_post_id].present?
|
||||||
post = Post.new(url: preflight[:url])
|
post = Post.new(url: preflight[:url])
|
||||||
@@ -273,13 +273,18 @@ class PostsController < ApplicationController
|
|||||||
return head :forbidden unless current_user.gte_member?
|
return head :forbidden unless current_user.gte_member?
|
||||||
return head :unsupported_media_type unless request.content_mime_type == Mime[:multipart_form]
|
return head :unsupported_media_type unless request.content_mime_type == Mime[:multipart_form]
|
||||||
return head :payload_too_large if request.content_length.to_i > MAX_BULK_REQUEST_BYTES
|
return head :payload_too_large if request.content_length.to_i > MAX_BULK_REQUEST_BYTES
|
||||||
|
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
posts = parse_bulk_posts_manifest
|
posts = parse_bulk_posts_manifest
|
||||||
thumbnails = parse_bulk_thumbnails(posts.length)
|
thumbnails = parse_bulk_thumbnails(posts.length)
|
||||||
|
|
||||||
result = PostBulkCreator.new(
|
result = PostBulkCreator.new(
|
||||||
actor: current_user,
|
actor: current_user,
|
||||||
posts:,
|
posts:,
|
||||||
thumbnails:,
|
thumbnails:,
|
||||||
host: request.base_url).run
|
host: request.base_url).run(locale)
|
||||||
|
|
||||||
render json: result
|
render json: result
|
||||||
rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
render_bad_request 'posts manifest の JSON が不正です.'
|
render_bad_request 'posts manifest の JSON が不正です.'
|
||||||
|
|||||||
@@ -406,10 +406,10 @@ class TagsController < ApplicationController
|
|||||||
return render_unprocessable_entity('カテゴリは必須です.', field: :category) if category.blank?
|
return render_unprocessable_entity('カテゴリは必須です.', field: :category) if category.blank?
|
||||||
return render_unprocessable_entity '廃止状態は必須です.', field: :deprecated unless params.key?(:deprecated)
|
return render_unprocessable_entity '廃止状態は必須です.', field: :deprecated unless params.key?(:deprecated)
|
||||||
|
|
||||||
return unless validate_tag_rename(tag, name)
|
|
||||||
|
|
||||||
locale = resolve_locale!
|
locale = resolve_locale!
|
||||||
|
|
||||||
|
return unless validate_tag_rename(locale, tag, name)
|
||||||
|
|
||||||
alias_names = params[:aliases].to_s.split.uniq
|
alias_names = params[:aliases].to_s.split.uniq
|
||||||
parent_names = params[:parent_tags].to_s.split.uniq
|
parent_names = params[:parent_tags].to_s.split.uniq
|
||||||
deprecated = bool?(:deprecated)
|
deprecated = bool?(:deprecated)
|
||||||
@@ -455,6 +455,8 @@ class TagsController < ApplicationController
|
|||||||
return head :unauthorized unless current_user
|
return head :unauthorized unless current_user
|
||||||
return head :forbidden unless current_user.gte_member?
|
return head :forbidden unless current_user.gte_member?
|
||||||
|
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
name = params[:name].presence
|
name = params[:name].presence
|
||||||
category = params[:category].presence
|
category = params[:category].presence
|
||||||
deprecated_given = params.key?(:deprecated)
|
deprecated_given = params.key?(:deprecated)
|
||||||
@@ -462,7 +464,7 @@ class TagsController < ApplicationController
|
|||||||
|
|
||||||
tag = Tag.find(params[:id])
|
tag = Tag.find(params[:id])
|
||||||
|
|
||||||
return unless validate_tag_rename(tag, name)
|
return unless validate_tag_rename(locale, tag, name)
|
||||||
|
|
||||||
if category.present? && category == 'nico'
|
if category.present? && category == 'nico'
|
||||||
return render_unprocessable_entity 'ニコタグは変更できません.', field: :category
|
return render_unprocessable_entity 'ニコタグは変更できません.', field: :category
|
||||||
@@ -684,7 +686,7 @@ class TagsController < ApplicationController
|
|||||||
created_by_user:)
|
created_by_user:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_tag_rename tag, name
|
def validate_tag_rename locale, tag, name
|
||||||
return true if name.blank? || name == tag.name
|
return true if name.blank? || name == tag.name
|
||||||
|
|
||||||
if tag.in?([Tag.tagme, Tag.bot, Tag.no_deerjikist, Tag.video, Tag.niconico])
|
if tag.in?([Tag.tagme, Tag.bot, Tag.no_deerjikist, Tag.video, Tag.niconico])
|
||||||
@@ -692,9 +694,8 @@ class TagsController < ApplicationController
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
target_tag_name = TagName.find_by(name:)
|
target_tag_name = TagName.find_by(language_code: locale.language_code, name:)
|
||||||
return true if target_tag_name.nil?
|
return true unless target_tag_name&.primary_flg
|
||||||
return true if target_tag_name.canonical_id?
|
|
||||||
|
|
||||||
render_unprocessable_entity 'その名前は既に使はれてゐます.', field: :name
|
render_unprocessable_entity 'その名前は既に使はれてゐます.', field: :name
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class Tag < ApplicationRecord
|
|||||||
raise SectionLiteralParseError.new(raw_name, raw_name)
|
raise SectionLiteralParseError.new(raw_name, raw_name)
|
||||||
end
|
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|
|
find_or_create_by_tag_name!(locale, name, category: (cat || :general)).tap do |tag|
|
||||||
if deny_deprecated && tag.deprecated?
|
if deny_deprecated && tag.deprecated?
|
||||||
@@ -235,10 +235,7 @@ class Tag < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
tag = tn.tag
|
tag = tn.tag
|
||||||
if tag
|
return tag if tag
|
||||||
tag.update!(tag_name_id: tn.id) if tag.tag_name_id != tn.id
|
|
||||||
return tag
|
|
||||||
end
|
|
||||||
|
|
||||||
tag = Tag.create!(tag_name: tn, category:)
|
tag = Tag.create!(tag_name: tn, category:)
|
||||||
tn.update!(tag:)
|
tn.update!(tag:)
|
||||||
@@ -279,6 +276,8 @@ class Tag < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
TagVersioning.record!(source_tag, event_type: :discard, created_by_user:)
|
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.destroy!
|
||||||
|
|
||||||
source_tag_name.update_columns(canonical_id: target_tag.tag_name_id,
|
source_tag_name.update_columns(canonical_id: target_tag.tag_name_id,
|
||||||
|
|||||||
@@ -1,24 +1,36 @@
|
|||||||
class TagName < ApplicationRecord
|
class TagName < ApplicationRecord
|
||||||
|
belongs_to :language, foreign_key: :language_code, primary_key: :code
|
||||||
belongs_to :tag, optional: true
|
belongs_to :tag, optional: true
|
||||||
has_one :wiki_page
|
has_one :wiki_page
|
||||||
|
|
||||||
belongs_to :canonical, class_name: 'TagName', optional: true
|
validates :name, presence: true,
|
||||||
has_many :aliases, class_name: 'TagName', foreign_key: :canonical_id
|
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 :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
|
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?)
|
names = Array(names).map { |n| n.to_s.strip }.reject(&:blank?)
|
||||||
return [] if names.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
|
end
|
||||||
|
|
||||||
def self.generate_name locale, tag, name
|
def self.generate_name locale, tag, name
|
||||||
@@ -29,21 +41,15 @@ class TagName < ApplicationRecord
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def canonical_must_be_canonical
|
|
||||||
if canonical&.canonical_id?
|
|
||||||
errors.add :canonical, 'canonical は実体を示す必要があります.'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def alias_name_must_not_have_prefix
|
def alias_name_must_not_have_prefix
|
||||||
if canonical_id? && name.to_s.include?(':')
|
if !(primary?) && name.to_s.include?(':')
|
||||||
errors.add :name, 'エーリアス名にプレフィクスを含むことはできません.'
|
errors.add :name, 'エーリアス名にプレフィクスを含むことはできません.'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def canonical_must_not_be_present_with_tag_or_wiki_page
|
def alias_must_not_have_wiki_page
|
||||||
if canonical_id? && (tag || wiki_page)
|
if !(primary?) && wiki_page
|
||||||
errors.add :canonical, 'タグもしくは Wiki の参照がある名前はエーリアスになれません.'
|
errors.add :primary_flg, 'Wiki 参照がある名前はエーリアスになれません.'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,23 +15,29 @@ class TagNameSanitisationRule < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def apply!
|
def apply!
|
||||||
TagName.find_each do |tn|
|
Language.find_each do |language|
|
||||||
|
TagName.where(language:).find_each do |tn|
|
||||||
name = sanitise(tn.name)
|
name = sanitise(tn.name)
|
||||||
next if name == tn.name
|
next if name == tn.name
|
||||||
|
|
||||||
TagName.transaction do
|
TagName.transaction do
|
||||||
existing_tn = TagName.find_by(name:)
|
existing_tn = TagName.find_by(language:, name:)
|
||||||
if existing_tn
|
if existing_tn
|
||||||
existing_tn = existing_tn.canonical || 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
|
next if existing_tn.id == tn.id
|
||||||
|
|
||||||
existing_tag = Tag.find_by(tag_name_id: existing_tn.id)
|
existing_tag = existing_tn.tag
|
||||||
source_tag = Tag.find_by(tag_name_id: tn.id)
|
source_tag = tn.tag
|
||||||
|
|
||||||
if existing_tag
|
if existing_tag
|
||||||
Tag.merge_tags!(existing_tag, source_tag) if tn.tag
|
Tag.merge_tags!(existing_tag, source_tag) if tn.tag
|
||||||
elsif source_tag
|
elsif source_tag
|
||||||
source_tag.update_columns(tag_name_id: existing_tn.id, updated_at: Time.current)
|
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
|
end
|
||||||
tn.destroy!
|
tn.destroy!
|
||||||
|
|
||||||
@@ -43,6 +49,7 @@ class TagNameSanitisationRule < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ class PostCreatePlan
|
|||||||
@existing_tags_by_name = nil
|
@existing_tags_by_name = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def build!
|
def build! locale
|
||||||
direct_tag_specs, tag_sections = parse_direct_tag_specs
|
direct_tag_specs, tag_sections = parse_direct_tag_specs(locale)
|
||||||
default_tag_specs = build_default_tag_specs(direct_tag_specs)
|
default_tag_specs = build_default_tag_specs(direct_tag_specs)
|
||||||
snapshot_tag_specs = merge_tag_specs(direct_tag_specs + default_tag_specs)
|
snapshot_tag_specs = merge_tag_specs(direct_tag_specs + default_tag_specs)
|
||||||
preload_existing_tags_by_name!(snapshot_tag_specs.map { _1[:name] })
|
preload_existing_tags_by_name!(snapshot_tag_specs.map { _1[:name] })
|
||||||
validate_new_tag_specs!(snapshot_tag_specs)
|
validate_new_tag_specs!(snapshot_tag_specs)
|
||||||
post_tag_specs = expand_parent_tag_specs(snapshot_tag_specs)
|
post_tag_specs = expand_parent_tag_specs(locale, snapshot_tag_specs)
|
||||||
video_ms = normalise_video_ms(snapshot_tag_specs)
|
video_ms = normalise_video_ms(snapshot_tag_specs)
|
||||||
validate_video_sections!(video_ms, tag_sections)
|
validate_video_sections!(video_ms, tag_sections)
|
||||||
parent_post_ids = normalise_parent_post_ids
|
parent_post_ids = normalise_parent_post_ids
|
||||||
@@ -42,13 +42,13 @@ class PostCreatePlan
|
|||||||
|
|
||||||
def tag_names = @attributes[:tags].to_s.split
|
def tag_names = @attributes[:tags].to_s.split
|
||||||
|
|
||||||
def parse_direct_tag_specs
|
def parse_direct_tag_specs locale
|
||||||
tag_sections = { }
|
tag_sections = { }
|
||||||
direct_tag_specs = []
|
direct_tag_specs = []
|
||||||
|
|
||||||
tag_names.each do |raw_name|
|
tag_names.each do |raw_name|
|
||||||
tag_name, category, sections = parse_raw_tag_name(raw_name)
|
tag_name, category, sections = parse_raw_tag_name(locale, raw_name)
|
||||||
existing_tag = existing_tags_by_name[tag_name]
|
existing_tag = existing_tags_by_name(locale)[tag_name]
|
||||||
raise Tag::DeprecatedTagNormalisationError, [existing_tag.name] if existing_tag&.deprecated?
|
raise Tag::DeprecatedTagNormalisationError, [existing_tag.name] if existing_tag&.deprecated?
|
||||||
|
|
||||||
direct_tag_specs << {
|
direct_tag_specs << {
|
||||||
@@ -65,7 +65,7 @@ class PostCreatePlan
|
|||||||
[merge_tag_specs(direct_tag_specs), tag_sections]
|
[merge_tag_specs(direct_tag_specs), tag_sections]
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_raw_tag_name raw_name
|
def parse_raw_tag_name locale, raw_name
|
||||||
name = raw_name.to_s
|
name = raw_name.to_s
|
||||||
prefix, category =
|
prefix, category =
|
||||||
Tag::CATEGORY_PREFIXES.find {
|
Tag::CATEGORY_PREFIXES.find {
|
||||||
@@ -74,7 +74,7 @@ class PostCreatePlan
|
|||||||
name = name.sub(/\A#{ prefix }/i, '')
|
name = name.sub(/\A#{ prefix }/i, '')
|
||||||
|
|
||||||
sections = []
|
sections = []
|
||||||
while (match = name.match(/\A(\S*?)\[([^\[\]\s]*)-([^\[\]\s]*)\](\S*)\z/))
|
while match = name.match(/\A(\S*?)\[([^\[\]\s]*)-([^\[\]\s]*)\](\S*)\z/)
|
||||||
name = "#{ match[1] }#{ match[4] }"
|
name = "#{ match[1] }#{ match[4] }"
|
||||||
next if match[2].empty? && match[3].empty?
|
next if match[2].empty? && match[3].empty?
|
||||||
|
|
||||||
@@ -87,17 +87,17 @@ class PostCreatePlan
|
|||||||
raise Tag::SectionLiteralParseError.new(raw_name, raw_name)
|
raise Tag::SectionLiteralParseError.new(raw_name, raw_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
[resolved_tag_name(name), category&.to_sym, sections]
|
[resolved_tag_name(locale, name), category&.to_sym, sections]
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_default_tag_specs direct_tag_specs
|
def build_default_tag_specs locale, direct_tag_specs
|
||||||
default_tag_specs = []
|
default_tag_specs = []
|
||||||
if direct_tag_specs.length < 10 && direct_tag_specs.none? { _1[:name] == TAGME_TAG_NAME }
|
if direct_tag_specs.length < 10 && direct_tag_specs.none? { _1[:name] == TAGME_TAG_NAME }
|
||||||
default_tag_specs << {
|
default_tag_specs << {
|
||||||
name: TAGME_TAG_NAME,
|
name: TAGME_TAG_NAME,
|
||||||
category: :meta }
|
category: :meta }
|
||||||
end
|
end
|
||||||
if direct_tag_specs.none? { deerjikist_tag_spec?(_1) }
|
if direct_tag_specs.none? { deerjikist_tag_spec?(locale, _1) }
|
||||||
default_tag_specs << {
|
default_tag_specs << {
|
||||||
name: NO_DEERJIKIST_TAG_NAME,
|
name: NO_DEERJIKIST_TAG_NAME,
|
||||||
category: :meta }
|
category: :meta }
|
||||||
@@ -131,8 +131,10 @@ class PostCreatePlan
|
|||||||
raise ActiveRecord::RecordInvalid, post
|
raise ActiveRecord::RecordInvalid, post
|
||||||
end
|
end
|
||||||
|
|
||||||
def expand_parent_tag_specs snapshot_tag_specs
|
def expand_parent_tag_specs locale, snapshot_tag_specs
|
||||||
existing_snapshot_tags = snapshot_tag_specs.filter_map { existing_tags_by_name[_1[:name]] }
|
existing_snapshot_tags = snapshot_tag_specs.filter_map do
|
||||||
|
existing_tags_by_name(locale)[_1[:name]]
|
||||||
|
end
|
||||||
expanded_parent_specs =
|
expanded_parent_specs =
|
||||||
Tag.expand_parent_tags(existing_snapshot_tags)
|
Tag.expand_parent_tags(existing_snapshot_tags)
|
||||||
.reject(&:deprecated?)
|
.reject(&:deprecated?)
|
||||||
@@ -156,33 +158,33 @@ class PostCreatePlan
|
|||||||
}.values.sort_by { _1[:name] }
|
}.values.sort_by { _1[:name] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def existing_tags_by_name
|
def existing_tags_by_name locale
|
||||||
@existing_tags_by_name ||= begin
|
@existing_tags_by_name ||= begin
|
||||||
names = tag_names.map { canonical_tag_name_without_sections(_1) }.uniq
|
names = tag_names.map { canonical_tag_name_without_sections(locale, _1) }.uniq
|
||||||
Tag.joins(:tag_name).where(tag_names: { name: names }).index_by(&:name)
|
Tag.joins(:tag_name).where(tag_names: { name: names }).index_by(&:name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def preload_existing_tags_by_name! names
|
def preload_existing_tags_by_name! locale, names
|
||||||
wanted_names = Array(names).map { _1.to_s }.reject(&:blank?).uniq
|
wanted_names = Array(names).map { _1.to_s }.reject(&:blank?).uniq
|
||||||
missing_names = wanted_names - existing_tags_by_name.keys
|
missing_names = wanted_names - existing_tags_by_name(locale).keys
|
||||||
return if missing_names.empty?
|
return if missing_names.empty?
|
||||||
|
|
||||||
existing_tags_by_name.merge!(
|
existing_tags_by_name(locale).merge!(
|
||||||
Tag.joins(:tag_name)
|
Tag.joins(:tag_name)
|
||||||
.where(tag_names: { name: missing_names })
|
.where(tag_names: { name: missing_names })
|
||||||
.index_by(&:name))
|
.index_by(&:name))
|
||||||
end
|
end
|
||||||
|
|
||||||
def canonical_tag_name_without_sections raw_name
|
def canonical_tag_name_without_sections locale, raw_name
|
||||||
name, = parse_raw_tag_name(raw_name)
|
name, = parse_raw_tag_name(locale, raw_name)
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
def deerjikist_tag_spec? spec
|
def deerjikist_tag_spec? locale, spec
|
||||||
return true if spec[:category] == :deerjikist
|
return true if spec[:category] == :deerjikist
|
||||||
|
|
||||||
existing_tags_by_name[spec[:name]]&.deerjikist?
|
existing_tags_by_name(locale)[spec[:name]]&.deerjikist?
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalise_parent_post_ids
|
def normalise_parent_post_ids
|
||||||
@@ -260,10 +262,13 @@ class PostCreatePlan
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolved_tag_name name
|
def resolved_tag_name locale, name
|
||||||
tag_name = TagName.includes(:canonical).find_by(name:)
|
tag_name = TagName.find_by!(language_code: locale.language_code, name:)
|
||||||
return name if tag_name.nil?
|
unless tag_name.primary_flg
|
||||||
|
tag_name = TagName.find_by!(language_code: locale.language_code,
|
||||||
(tag_name.canonical || tag_name).name
|
tag_id: tag_name.tag_id,
|
||||||
|
primary_flg: true)
|
||||||
|
end
|
||||||
|
tag_name.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ class PostCreator
|
|||||||
ApplicationRecord.transaction do
|
ApplicationRecord.transaction do
|
||||||
post.save!
|
post.save!
|
||||||
post.thumbnail.attach(thumbnail_attachment) if thumbnail_attachment.present?
|
post.thumbnail.attach(thumbnail_attachment) if thumbnail_attachment.present?
|
||||||
snapshot_tags = planned_snapshot_tags
|
snapshot_tags = planned_snapshot_tags(locale)
|
||||||
post_tags = planned_post_tags
|
post_tags = planned_post_tags(locale)
|
||||||
sections = planned_sections
|
sections = planned_sections(locale)
|
||||||
TagVersioning.record_tag_snapshots!(snapshot_tags, created_by_user: @actor)
|
TagVersioning.record_tag_snapshots!(snapshot_tags, created_by_user: @actor)
|
||||||
post.video_ms = planned_video_ms(locale)
|
post.video_ms = planned_video_ms(locale)
|
||||||
post.save!
|
post.save!
|
||||||
sync_post_tags!(post, post_tags, sections)
|
sync_post_tags!(post, post_tags, sections)
|
||||||
sync_parent_posts!(post, planned_parent_post_ids)
|
sync_parent_posts!(post, planned_parent_post_ids(locale))
|
||||||
PostVersionRecorder.record!(post:, event_type: :create, created_by_user: @actor)
|
PostVersionRecorder.record!(post:, event_type: :create, created_by_user: @actor)
|
||||||
end
|
end
|
||||||
post
|
post
|
||||||
@@ -45,13 +45,15 @@ class PostCreator
|
|||||||
thumbnail_base: @attributes[:thumbnail_base].presence)
|
thumbnail_base: @attributes[:thumbnail_base].presence)
|
||||||
end
|
end
|
||||||
|
|
||||||
def planned_snapshot_tags = planned_create_attributes[:snapshot_tags]
|
def planned_snapshot_tags(locale) = planned_create_attributes(locale)[:snapshot_tags]
|
||||||
|
|
||||||
def planned_post_tags = planned_create_attributes[:post_tags]
|
def planned_post_tags(locale) = planned_create_attributes(locale)[:post_tags]
|
||||||
|
|
||||||
def planned_sections = planned_create_attributes[:tag_sections]
|
def planned_sections(locale) = planned_create_attributes(locale)[:tag_sections]
|
||||||
|
|
||||||
def planned_parent_post_ids = planned_create_attributes[:normalised_parent_post_ids]
|
def planned_parent_post_ids locale
|
||||||
|
planned_create_attributes(locale)[:normalised_parent_post_ids]
|
||||||
|
end
|
||||||
|
|
||||||
def planned_video_ms locale
|
def planned_video_ms locale
|
||||||
planned_create_attributes(locale)[:video_ms]
|
planned_create_attributes(locale)[:video_ms]
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ RSpec.describe 'discarded tag cleanup migrations' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'with legacy records' do
|
context 'with legacy records' do
|
||||||
|
# Reproduce the historical schema required by these pre-multilingual migrations.
|
||||||
self.use_transactional_tests = false
|
self.use_transactional_tests = false
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|||||||
@@ -7,15 +7,6 @@ FactoryBot.define do
|
|||||||
|
|
||||||
trait :alias do
|
trait :alias do
|
||||||
primary_flg { false }
|
primary_flg { false }
|
||||||
|
|
||||||
after(:create) do |tag_name|
|
|
||||||
owner = tag_name.canonical&.tag
|
|
||||||
raise ArgumentError, 'alias requires a canonical tag' unless owner
|
|
||||||
|
|
||||||
# The alias validation still rejects tag_id; its contract is tested separately.
|
|
||||||
tag_name.update_columns(tag_id: owner.id)
|
|
||||||
tag_name.association(:tag).reset
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ RSpec.describe Locale, type: :model do
|
|||||||
expect(first.tag_names.find_by!(language_code: 'fr', primary_flg: true))
|
expect(first.tag_names.find_by!(language_code: 'fr', primary_flg: true))
|
||||||
.to have_attributes(name: 'name_from_generator', tag_id: first.id,
|
.to have_attributes(name: 'name_from_generator', tag_id: first.id,
|
||||||
language_code: 'fr', script_code: 'Latn',
|
language_code: 'fr', script_code: 'Latn',
|
||||||
primary_flg: true, canonical_id: nil)
|
primary_flg: true)
|
||||||
expect(second.tag_names.find_by!(language_code: 'fr', primary_flg: true))
|
expect(second.tag_names.find_by!(language_code: 'fr', primary_flg: true))
|
||||||
.to have_attributes(tag_id: second.id, language_code: 'fr',
|
.to have_attributes(tag_id: second.id, language_code: 'fr',
|
||||||
script_code: 'Latn', primary_flg: true, canonical_id: nil)
|
script_code: 'Latn', primary_flg: true)
|
||||||
expect(TagName.where(language_code: 'fr', primary_flg: true,
|
expect(TagName.where(language_code: 'fr', primary_flg: true,
|
||||||
tag_id: [first.id, second.id]).count).to eq(2)
|
tag_id: [first.id, second.id]).count).to eq(2)
|
||||||
end
|
end
|
||||||
@@ -53,13 +53,13 @@ RSpec.describe Locale, type: :model do
|
|||||||
prepare_french_reference!
|
prepare_french_reference!
|
||||||
tag = create(:tag, name: 'alias_only_tag')
|
tag = create(:tag, name: 'alias_only_tag')
|
||||||
alias_name = create(:tag_name, :alias, name: 'alias_fr',
|
alias_name = create(:tag_name, :alias, name: 'alias_fr',
|
||||||
canonical: tag.tag_name,
|
tag:,
|
||||||
language_code: 'fr', script_code: 'Latn')
|
language_code: 'fr', script_code: 'Latn')
|
||||||
|
|
||||||
create_french_locale!
|
create_french_locale!
|
||||||
|
|
||||||
expect(alias_name.reload).to have_attributes(
|
expect(alias_name.reload).to have_attributes(
|
||||||
canonical_id: tag.tag_name_id, tag_id: tag.id,
|
tag_id: tag.id,
|
||||||
language_code: 'fr', script_code: 'Latn', primary_flg: false)
|
language_code: 'fr', script_code: 'Latn', primary_flg: false)
|
||||||
generated = TagName.find_by!(tag_id: tag.id, language_code: 'fr', primary_flg: true)
|
generated = TagName.find_by!(tag_id: tag.id, language_code: 'fr', primary_flg: true)
|
||||||
expect(generated).to have_attributes(tag_id: tag.id, language_code: 'fr',
|
expect(generated).to have_attributes(tag_id: tag.id, language_code: 'fr',
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ RSpec.describe TagNameSanitisationRule, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a conflicting canonical tag_name exists' do
|
context 'when a conflicting primary tag name exists' do
|
||||||
let!(:existing) { create(:tag_name, name: 'foobar') }
|
let!(:existing) { create(:tag_name, name: 'foobar') }
|
||||||
let!(:source) do
|
let!(:source) do
|
||||||
create(:tag_name, name: 'tmp').tap do |tn|
|
create(:tag_name, name: 'tmp').tap do |tn|
|
||||||
@@ -105,8 +105,7 @@ RSpec.describe TagNameSanitisationRule, type: :model do
|
|||||||
|
|
||||||
it 'moves the tag to the existing tag_name' do
|
it 'moves the tag to the existing tag_name' do
|
||||||
described_class.apply!
|
described_class.apply!
|
||||||
expected_tag_name_id = existing.canonical_id || existing.id
|
expect(source_tag.reload.tag_name_id).to eq(existing.id)
|
||||||
expect(source_tag.reload.tag_name_id).to eq(expected_tag_name_id)
|
|
||||||
expect(TagName.unscoped.exists?(source_tag_name_id)).to be(false)
|
expect(TagName.unscoped.exists?(source_tag_name_id)).to be(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -114,7 +113,7 @@ RSpec.describe TagNameSanitisationRule, type: :model do
|
|||||||
context 'when the sanitised name is an alias of an existing tag' do
|
context 'when the sanitised name is an alias of an existing tag' do
|
||||||
let!(:existing_tag) { create(:tag) }
|
let!(:existing_tag) { create(:tag) }
|
||||||
let!(:alias_name) do
|
let!(:alias_name) do
|
||||||
create(:tag_name, :alias, name: 'foobar', canonical: existing_tag.tag_name)
|
create(:tag_name, :alias, name: 'foobar', tag: existing_tag)
|
||||||
end
|
end
|
||||||
let!(:source) do
|
let!(:source) do
|
||||||
create(:tag_name, name: 'tmp').tap do |tn|
|
create(:tag_name, name: 'tmp').tap do |tn|
|
||||||
@@ -122,11 +121,15 @@ RSpec.describe TagNameSanitisationRule, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'deletes only the source and preserves the alias and its canonical tag' do
|
it 'deletes only the source and preserves the alias and its owning tag' do
|
||||||
described_class.apply!
|
described_class.apply!
|
||||||
|
|
||||||
expect(TagName.unscoped.exists?(source.id)).to be(false)
|
expect(TagName.unscoped.exists?(source.id)).to be(false)
|
||||||
expect(alias_name.reload.canonical).to eq(existing_tag.tag_name)
|
expect(alias_name.reload).to have_attributes(
|
||||||
|
tag_id: existing_tag.id, language_code: 'ja', primary_flg: false)
|
||||||
|
expect(TagName.find_by!(tag_id: existing_tag.id,
|
||||||
|
language_code: 'ja', primary_flg: true))
|
||||||
|
.to eq(existing_tag.tag_name)
|
||||||
expect(Tag.find(existing_tag.id)).to eq(existing_tag)
|
expect(Tag.find(existing_tag.id)).to eq(existing_tag)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,37 +32,58 @@ RSpec.describe TagName, type: :model do
|
|||||||
|
|
||||||
expect(tag.reload.tag_name.reload.tag_id).to eq(tag.id)
|
expect(tag.reload.tag_name.reload.tag_id).to eq(tag.id)
|
||||||
expect(tag.tag_name.tag).to eq(tag)
|
expect(tag.tag_name.tag).to eq(tag)
|
||||||
|
expect(described_class.find_by!(tag_id: tag.id, language_code: 'ja', primary_flg: true))
|
||||||
|
.to eq(tag.tag_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'accepts an alias owned by the canonical tag' do
|
it 'persists an alias owned by the same tag as its primary name' do
|
||||||
tag = create(:tag)
|
tag = create(:tag)
|
||||||
alias_name = build(:tag_name, name: 'valid_alias', canonical: tag.tag_name,
|
alias_name = create(:tag_name, :alias, name: 'valid_alias', tag:)
|
||||||
tag:, primary_flg: false)
|
|
||||||
|
|
||||||
expect(alias_name).to have_attributes(
|
expect(alias_name.reload).to have_attributes(
|
||||||
canonical_id: tag.tag_name_id, tag_id: tag.id,
|
tag_id: tag.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
expect(alias_name).to be_valid
|
primary = described_class.find_by!(tag_id: alias_name.tag_id,
|
||||||
|
language_code: alias_name.language_code,
|
||||||
|
primary_flg: true)
|
||||||
|
expect(primary).to eq(tag.tag_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.canonicalise' do
|
describe '.canonicalise' do
|
||||||
|
it 'resolves the primary name of the alias language on the same tag' do
|
||||||
|
tag = create(:tag, name: '日本語正本')
|
||||||
|
english_primary = create(:tag_name, tag:, name: 'english_primary',
|
||||||
|
language_code: 'en', script_code: 'Latn')
|
||||||
|
english_alias = create(:tag_name, :alias, tag:, name: 'english_alias',
|
||||||
|
language_code: 'en', script_code: 'Latn')
|
||||||
|
representative_id = tag.tag_name_id
|
||||||
|
|
||||||
|
primary = described_class.find_by!(tag_id: english_alias.tag_id,
|
||||||
|
language_code: english_alias.language_code,
|
||||||
|
primary_flg: true)
|
||||||
|
|
||||||
|
expect(primary).to eq(english_primary)
|
||||||
|
expect(described_class.canonicalise(locale, [english_alias.name]))
|
||||||
|
.to eq([english_primary.name])
|
||||||
|
expect(tag.reload.tag_name_id).to eq(representative_id)
|
||||||
|
end
|
||||||
|
|
||||||
it 'resolves only aliases in the requested language' do
|
it 'resolves only aliases in the requested language' do
|
||||||
japanese = create(:tag, name: 'japanese_canonical')
|
japanese = create(:tag, name: 'japanese_canonical')
|
||||||
english_name = create(:tag_name, name: 'english_canonical',
|
english_name = create(:tag_name, name: 'english_canonical',
|
||||||
language_code: 'en', script_code: 'Latn')
|
language_code: 'en', script_code: 'Latn')
|
||||||
english = create(:tag, tag_name: english_name)
|
english = create(:tag, tag_name: english_name)
|
||||||
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: japanese.tag_name)
|
tag: japanese)
|
||||||
english_alias = create(:tag_name, :alias, name: 'temporary_alias',
|
english_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: english_name,
|
tag: english,
|
||||||
language_code: 'en', script_code: 'Latn')
|
language_code: 'en', script_code: 'Latn')
|
||||||
english_alias.update_columns(name: 'shared_alias')
|
|
||||||
|
|
||||||
expect(japanese_alias.reload).to have_attributes(
|
expect(japanese_alias.reload).to have_attributes(
|
||||||
canonical_id: japanese.tag_name_id, tag_id: japanese.id,
|
tag_id: japanese.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
expect(english_alias.reload).to have_attributes(
|
expect(english_alias.reload).to have_attributes(
|
||||||
canonical_id: english_name.id, tag_id: english.id,
|
tag_id: english.id,
|
||||||
primary_flg: false, language_code: 'en')
|
primary_flg: false, language_code: 'en')
|
||||||
expect(described_class.canonicalise(locale, ['shared_alias']))
|
expect(described_class.canonicalise(locale, ['shared_alias']))
|
||||||
.to eq(['english_canonical'])
|
.to eq(['english_canonical'])
|
||||||
|
|||||||
@@ -37,17 +37,16 @@ RSpec.describe Tag, type: :model do
|
|||||||
language_code: 'en', script_code: 'Latn')
|
language_code: 'en', script_code: 'Latn')
|
||||||
english = create(:tag, tag_name: english_name)
|
english = create(:tag, tag_name: english_name)
|
||||||
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: japanese.tag_name)
|
tag: japanese)
|
||||||
english_alias = create(:tag_name, :alias, name: 'temporary_alias',
|
english_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: english_name,
|
tag: english,
|
||||||
language_code: 'en', script_code: 'Latn')
|
language_code: 'en', script_code: 'Latn')
|
||||||
english_alias.update_columns(name: 'shared_alias')
|
|
||||||
|
|
||||||
expect(japanese_alias.reload).to have_attributes(
|
expect(japanese_alias.reload).to have_attributes(
|
||||||
canonical_id: japanese.tag_name_id, tag_id: japanese.id,
|
tag_id: japanese.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
expect(english_alias.reload).to have_attributes(
|
expect(english_alias.reload).to have_attributes(
|
||||||
canonical_id: english_name.id, tag_id: english.id,
|
tag_id: english.id,
|
||||||
primary_flg: false, language_code: 'en')
|
primary_flg: false, language_code: 'en')
|
||||||
expect(described_class.normalise_tags!(
|
expect(described_class.normalise_tags!(
|
||||||
english_locale, ['shared_alias'],
|
english_locale, ['shared_alias'],
|
||||||
@@ -270,12 +269,12 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(tag.category).to eq('character')
|
expect(tag.category).to eq('character')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'reuses the canonical tag for an alias without changing its category' do
|
it 'reuses the owning tag for an alias without changing its category' do
|
||||||
tag = create(:tag, category: :character)
|
tag = create(:tag, category: :character)
|
||||||
representative_id = tag.tag_name_id
|
representative_id = tag.tag_name_id
|
||||||
alias_name = create(:tag_name, :alias, name: 'lookup_alias', canonical: tag.tag_name)
|
alias_name = create(:tag_name, :alias, name: 'lookup_alias', tag:)
|
||||||
expect(alias_name.reload).to have_attributes(
|
expect(alias_name.reload).to have_attributes(
|
||||||
canonical_id: tag.tag_name_id, tag_id: tag.id,
|
tag_id: tag.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
found = nil
|
found = nil
|
||||||
|
|
||||||
@@ -289,14 +288,14 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(tag.reload.tag_name_id).to eq(representative_id)
|
expect(tag.reload.tag_name_id).to eq(representative_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'reuses the canonical tag through another alias' do
|
it 'reuses the owning tag through another alias' do
|
||||||
tag = create(:tag)
|
tag = create(:tag)
|
||||||
canonical = tag.tag_name
|
primary = tag.tag_name
|
||||||
alias_name = create(:tag_name, :alias, name: 'lookup_alias', canonical:)
|
alias_name = create(:tag_name, :alias, name: 'lookup_alias', tag:)
|
||||||
other_alias = create(:tag_name, :alias, name: 'lookup_other_alias', canonical:)
|
other_alias = create(:tag_name, :alias, name: 'lookup_other_alias', tag:)
|
||||||
|
|
||||||
expect([alias_name.reload, other_alias.reload]).to all(have_attributes(
|
expect([alias_name.reload, other_alias.reload]).to all(have_attributes(
|
||||||
canonical_id: canonical.id, tag_id: tag.id,
|
tag_id: tag.id,
|
||||||
primary_flg: false, language_code: 'ja'))
|
primary_flg: false, language_code: 'ja'))
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
@@ -305,7 +304,7 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(found).to eq(tag)
|
expect(found).to eq(tag)
|
||||||
}.to change(Tag, :count).by(0).and change(TagName, :count).by(0)
|
}.to change(Tag, :count).by(0).and change(TagName, :count).by(0)
|
||||||
|
|
||||||
expect(tag.tag_name).to eq(canonical)
|
expect(tag.reload.tag_name).to eq(primary)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -329,7 +328,8 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(PostTag.exists?(post: post_record, tag: source_tag)).to be(false)
|
expect(PostTag.exists?(post: post_record, tag: source_tag)).to be(false)
|
||||||
expect(target_link).to be_present
|
expect(target_link).to be_present
|
||||||
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
||||||
expect(source_tag_name.reload.canonical_id).to eq(target_tag.tag_name_id)
|
expect(source_tag_name.reload).to have_attributes(
|
||||||
|
tag_id: target_tag.id, language_code: 'ja', primary_flg: false)
|
||||||
expect(target_tag.reload.post_count).to eq(1)
|
expect(target_tag.reload.post_count).to eq(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -355,7 +355,8 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(target_post_tag.reload.sections).to contain_exactly(target_section)
|
expect(target_post_tag.reload.sections).to contain_exactly(target_section)
|
||||||
|
|
||||||
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
||||||
expect(source_tag_name.reload.canonical_id).to eq(target_tag.tag_name_id)
|
expect(source_tag_name.reload).to have_attributes(
|
||||||
|
tag_id: target_tag.id, language_code: 'ja', primary_flg: false)
|
||||||
expect(target_tag.reload.post_count).to eq(1)
|
expect(target_tag.reload.post_count).to eq(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -363,7 +364,7 @@ RSpec.describe Tag, type: :model do
|
|||||||
it 'keeps source history and records the new target alias after deleting the source' do
|
it 'keeps source history and records the new target alias after deleting the source' do
|
||||||
user = create_member_user!
|
user = create_member_user!
|
||||||
source_name = source_tag.name
|
source_name = source_tag.name
|
||||||
source_alias = create(:tag_name, :alias, name: 'merge_alias', canonical: source_tag_name)
|
source_alias = create(:tag_name, :alias, name: 'merge_alias', tag: source_tag)
|
||||||
TagVersioning.ensure_snapshot!(source_tag, created_by_user: user)
|
TagVersioning.ensure_snapshot!(source_tag, created_by_user: user)
|
||||||
original_version = source_tag.tag_versions.first
|
original_version = source_tag.tag_versions.first
|
||||||
|
|
||||||
@@ -433,7 +434,8 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
||||||
expect(PostTag.exists?(post: post_record, tag: source_tag)).to be(false)
|
expect(PostTag.exists?(post: post_record, tag: source_tag)).to be(false)
|
||||||
expect(target_link).to be_present
|
expect(target_link).to be_present
|
||||||
expect(source_tag_name.reload.canonical_id).to eq(target_tag.tag_name_id)
|
expect(source_tag_name.reload).to have_attributes(
|
||||||
|
tag_id: target_tag.id, language_code: 'ja', primary_flg: false)
|
||||||
expect(target_tag.reload.post_count).to eq(1)
|
expect(target_tag.reload.post_count).to eq(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -464,7 +466,8 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(target_link).to be_present
|
expect(target_link).to be_present
|
||||||
|
|
||||||
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
expect(Tag.unscoped.exists?(source_tag.id)).to be(false)
|
||||||
expect(source_tag_name.reload.canonical_id).to eq(target_tag.tag_name_id)
|
expect(source_tag_name.reload).to have_attributes(
|
||||||
|
tag_id: target_tag.id, language_code: 'ja', primary_flg: false)
|
||||||
expect(target_tag.reload.post_count).to eq(1)
|
expect(target_tag.reload.post_count).to eq(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -493,7 +496,8 @@ RSpec.describe Tag, type: :model do
|
|||||||
}.to raise_error(ActiveRecord::RecordInvalid)
|
}.to raise_error(ActiveRecord::RecordInvalid)
|
||||||
|
|
||||||
expect(Tag.unscoped.exists?(earlier_source.id)).to be(true)
|
expect(Tag.unscoped.exists?(earlier_source.id)).to be(true)
|
||||||
expect(earlier_name.reload.canonical_id).to be_nil
|
expect(earlier_name.reload).to have_attributes(
|
||||||
|
tag_id: earlier_source.id, language_code: 'ja', primary_flg: true)
|
||||||
expect(TagVersion.where(tag_id: [earlier_source.id, source_tag.id, target_tag.id]))
|
expect(TagVersion.where(tag_id: [earlier_source.id, source_tag.id, target_tag.id]))
|
||||||
.to be_empty
|
.to be_empty
|
||||||
expect(Tag.unscoped.exists?(source_tag.id)).to be(true)
|
expect(Tag.unscoped.exists?(source_tag.id)).to be(true)
|
||||||
@@ -502,7 +506,8 @@ RSpec.describe Tag, type: :model do
|
|||||||
expect(source_post_tag.sections).to contain_exactly(source_section)
|
expect(source_post_tag.sections).to contain_exactly(source_section)
|
||||||
expect(PostTag.find_by(post: post_record, tag: target_tag)).to be_nil
|
expect(PostTag.find_by(post: post_record, tag: target_tag)).to be_nil
|
||||||
expect(source_tag.reload.post_count).to eq(1)
|
expect(source_tag.reload.post_count).to eq(1)
|
||||||
expect(source_tag_name.reload.canonical_id).to be_nil
|
expect(source_tag_name.reload).to have_attributes(
|
||||||
|
tag_id: source_tag.id, language_code: 'ja', primary_flg: true)
|
||||||
expect(target_tag.reload.post_count).to eq(0)
|
expect(target_tag.reload.post_count).to eq(0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -202,17 +202,19 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
|
|||||||
expect(response).to have_http_status(:ok), response.body
|
expect(response).to have_http_status(:ok), response.body
|
||||||
expect(TagName.find_by!(language_code: 'en', name: 'english_alias'))
|
expect(TagName.find_by!(language_code: 'en', name: 'english_alias'))
|
||||||
.to have_attributes(
|
.to have_attributes(
|
||||||
script_code: 'Latn', canonical_id: english_name.id,
|
script_code: 'Latn',
|
||||||
tag_id: tag.id, primary_flg: false, language_code: 'en')
|
tag_id: tag.id, primary_flg: false, language_code: 'en')
|
||||||
expect(tag.reload.tag_name_id).to eq(english_name.id)
|
expect(tag.reload.tag_name_id).to eq(english_name.id)
|
||||||
|
primary = TagName.find_by!(tag_id: tag.id, language_code: 'en', primary_flg: true)
|
||||||
|
expect(primary).to have_attributes(name: 'english_original', script_code: 'Latn')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not take an alias from another language' do
|
it 'does not take an alias from another language' do
|
||||||
japanese = create(:tag, name: 'japanese_owner')
|
japanese = create(:tag, name: 'japanese_owner')
|
||||||
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: japanese.tag_name)
|
tag: japanese)
|
||||||
expect(japanese_alias.reload).to have_attributes(
|
expect(japanese_alias.reload).to have_attributes(
|
||||||
canonical_id: japanese.tag_name_id, tag_id: japanese.id,
|
tag_id: japanese.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
|
|
||||||
put "/tags/#{ tag.id }", params: {
|
put "/tags/#{ tag.id }", params: {
|
||||||
@@ -221,12 +223,14 @@ RSpec.describe 'Locale propagation on write paths', type: :request do
|
|||||||
|
|
||||||
expect(response).to have_http_status(:ok), response.body
|
expect(response).to have_http_status(:ok), response.body
|
||||||
expect(japanese_alias.reload).to have_attributes(
|
expect(japanese_alias.reload).to have_attributes(
|
||||||
canonical_id: japanese.tag_name_id, tag_id: japanese.id,
|
tag_id: japanese.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
expect(TagName.find_by!(language_code: 'en', name: 'shared_alias'))
|
expect(TagName.find_by!(language_code: 'en', name: 'shared_alias'))
|
||||||
.to have_attributes(
|
.to have_attributes(
|
||||||
canonical_id: english_name.id, tag_id: tag.id,
|
tag_id: tag.id, script_code: 'Latn',
|
||||||
primary_flg: false, language_code: 'en')
|
primary_flg: false, language_code: 'en')
|
||||||
|
expect(TagName.where(name: 'shared_alias').pluck(:language_code, :tag_id))
|
||||||
|
.to contain_exactly(['ja', japanese.id], ['en', tag.id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ RSpec.describe 'Posts API', type: :request do
|
|||||||
let!(:tag) { create(:tag, tag_name:, category: :general) }
|
let!(:tag) { create(:tag, tag_name:, category: :general) }
|
||||||
let!(:tag_name2) { create(:tag_name, name: 'unko') }
|
let!(:tag_name2) { create(:tag_name, name: 'unko') }
|
||||||
let!(:tag2) { create(:tag, tag_name: tag_name2, category: :deerjikist) }
|
let!(:tag2) { create(:tag, tag_name: tag_name2, category: :deerjikist) }
|
||||||
let!(:alias_tag_name) { create(:tag_name, :alias, name: 'manko', canonical: tag_name) }
|
let!(:alias_tag_name) { create(:tag_name, :alias, name: 'manko', tag:) }
|
||||||
|
|
||||||
let!(:hit_post) do
|
let!(:hit_post) do
|
||||||
Post.create!(uploaded_user: user, title: 'hello spec world',
|
Post.create!(uploaded_user: user, title: 'hello spec world',
|
||||||
@@ -351,7 +351,7 @@ RSpec.describe 'Posts API', type: :request do
|
|||||||
let!(:baz_tag) { create(:tag, tag_name: baz_tag_name, category: :general) }
|
let!(:baz_tag) { create(:tag, tag_name: baz_tag_name, category: :general) }
|
||||||
|
|
||||||
let!(:foo_alias_tag_name) do
|
let!(:foo_alias_tag_name) do
|
||||||
create(:tag_name, :alias, name: 'not_spec_foo_alias', canonical: foo_tag_name)
|
create(:tag_name, :alias, name: 'not_spec_foo_alias', tag: foo_tag)
|
||||||
end
|
end
|
||||||
|
|
||||||
let!(:foo_only_post) do
|
let!(:foo_only_post) do
|
||||||
@@ -854,7 +854,7 @@ RSpec.describe 'Posts API', type: :request do
|
|||||||
15.times.map do |i|
|
15.times.map do |i|
|
||||||
tag_name = create(:tag_name, name: "show_query_tag_#{ i }")
|
tag_name = create(:tag_name, name: "show_query_tag_#{ i }")
|
||||||
tag = create(:tag, tag_name:, category: :general)
|
tag = create(:tag, tag_name:, category: :general)
|
||||||
create(:tag_name, :alias, name: "show_query_alias_#{ i }", canonical: tag_name)
|
create(:tag_name, :alias, name: "show_query_alias_#{ i }", tag:)
|
||||||
PostTag.create!(post: post_record, tag:)
|
PostTag.create!(post: post_record, tag:)
|
||||||
tag
|
tag
|
||||||
end
|
end
|
||||||
@@ -999,7 +999,7 @@ RSpec.describe 'Posts API', type: :request do
|
|||||||
|
|
||||||
describe 'POST /posts' do
|
describe 'POST /posts' do
|
||||||
let(:member) { create(:user, :member) }
|
let(:member) { create(:user, :member) }
|
||||||
let!(:alias_tag_name) { create(:tag_name, :alias, name: 'manko', canonical: tag_name) }
|
let!(:alias_tag_name) { create(:tag_name, :alias, name: 'manko', tag:) }
|
||||||
|
|
||||||
it '401 when not logged in' do
|
it '401 when not logged in' do
|
||||||
sign_out
|
sign_out
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ require 'rails_helper'
|
|||||||
RSpec.describe 'Tags API', type: :request do
|
RSpec.describe 'Tags API', type: :request do
|
||||||
let!(:tn) { create(:tag_name, name: 'spec_tag') }
|
let!(:tn) { create(:tag_name, name: 'spec_tag') }
|
||||||
let!(:tag) { create(:tag, tag_name: tn, category: :general) }
|
let!(:tag) { create(:tag, tag_name: tn, category: :general) }
|
||||||
let!(:alias_tn) { create(:tag_name, :alias, name: 'unko', canonical: tn) }
|
let!(:alias_tn) { create(:tag_name, :alias, name: 'unko', tag:) }
|
||||||
let!(:post) { Post.create!(url: 'https://example.com/unkounkounko') }
|
let!(:post) { Post.create!(url: 'https://example.com/unkounkounko') }
|
||||||
let!(:post_tag) { PostTag.create!(post:, tag:) }
|
let!(:post_tag) { PostTag.create!(post:, tag:) }
|
||||||
let!(:tn2) { create(:tag_name, name: 'unknown') }
|
let!(:tn2) { create(:tag_name, name: 'unknown') }
|
||||||
@@ -466,7 +466,7 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
it 'excludes external tags but preserves internal alias matches when nico is false' do
|
it 'excludes external tags but preserves internal alias matches when nico is false' do
|
||||||
internal = create(:tag, category: :general, name: 'switch_internal', post_count: 1)
|
internal = create(:tag, category: :general, name: 'switch_internal', post_count: 1)
|
||||||
alias_target = create(:tag, category: :general, name: 'alias_target', post_count: 1)
|
alias_target = create(:tag, category: :general, name: 'alias_target', post_count: 1)
|
||||||
create(:tag_name, :alias, name: 'switch_alias', canonical: alias_target.tag_name)
|
create(:tag_name, :alias, name: 'switch_alias', tag: alias_target)
|
||||||
create(:external_tag, name: 'switch_external', post_count: 1)
|
create(:external_tag, name: 'switch_external', post_count: 1)
|
||||||
|
|
||||||
get '/tags/autocomplete', params: { q: 'switch', nico: '0' }
|
get '/tags/autocomplete', params: { q: 'switch', nico: '0' }
|
||||||
@@ -479,13 +479,13 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
end
|
end
|
||||||
|
|
||||||
['%', '_'].each do |wildcard|
|
['%', '_'].each do |wildcard|
|
||||||
it "treats #{ wildcard } literally for canonical, alias, and external names" do
|
it "treats #{ wildcard } literally for primary, alias, and external names" do
|
||||||
literal = "literal#{ wildcard }match"
|
literal = "literal#{ wildcard }match"
|
||||||
create(:tag, category: :general, name: literal, post_count: 1)
|
create(:tag, category: :general, name: literal, post_count: 1)
|
||||||
alias_target = create(
|
alias_target = create(
|
||||||
:tag, category: :general, name: 'literal_alias_target', post_count: 1)
|
:tag, category: :general, name: 'literal_alias_target', post_count: 1)
|
||||||
create(:tag_name, :alias, name: "#{ literal }_alias",
|
create(:tag_name, :alias, name: "#{ literal }_alias",
|
||||||
canonical: alias_target.tag_name)
|
tag: alias_target)
|
||||||
create(:external_tag, name: literal, post_count: 1)
|
create(:external_tag, name: literal, post_count: 1)
|
||||||
create(:tag, category: :general, name: 'literalXmatch', post_count: 2)
|
create(:tag, category: :general, name: 'literalXmatch', post_count: 2)
|
||||||
create(:external_tag, name: 'literalXmatch', post_count: 2)
|
create(:external_tag, name: 'literalXmatch', post_count: 2)
|
||||||
@@ -509,7 +509,7 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
expect(t['matched_alias']).to be(nil)
|
expect(t['matched_alias']).to be(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns matching canonical tags by q with aliases' do
|
it 'returns matching primary tag names by q with aliases' do
|
||||||
get '/tags/autocomplete', params: { q: 'unk' }
|
get '/tags/autocomplete', params: { q: 'unk' }
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
@@ -772,7 +772,8 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
expect(TagName.find_by!(name: 'spec_tag').canonical).to eq(tag.reload.tag_name)
|
expect(TagName.find_by!(language_code: 'ja', name: 'spec_tag'))
|
||||||
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
|
|
||||||
patch "/tags/#{ tag.id }", params: { name: 'spec_tag' }
|
patch "/tags/#{ tag.id }", params: { name: 'spec_tag' }
|
||||||
|
|
||||||
@@ -781,8 +782,10 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
tag.reload
|
tag.reload
|
||||||
|
|
||||||
expect(tag.name).to eq('spec_tag')
|
expect(tag.name).to eq('spec_tag')
|
||||||
expect(tag.tag_name.canonical_id).to be_nil
|
expect(tag.tag_name).to have_attributes(
|
||||||
expect(TagName.find_by!(name: 'patch_roundtrip_target').canonical).to eq(tag.tag_name)
|
tag_id: tag.id, language_code: 'ja', primary_flg: true)
|
||||||
|
expect(TagName.find_by!(language_code: 'ja', name: 'patch_roundtrip_target'))
|
||||||
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it '別 tag の正規名には変更できない' do
|
it '別 tag の正規名には変更できない' do
|
||||||
@@ -801,7 +804,8 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(tag.reload.name).to eq('spec_tag')
|
expect(tag.reload.name).to eq('spec_tag')
|
||||||
expect(tag.tag_name.aliases.map(&:name)).to contain_exactly('unko')
|
expect(TagName.where(tag_id: tag.id, language_code: 'ja', primary_flg: false).pluck(:name))
|
||||||
|
.to contain_exactly('unko')
|
||||||
expect(wiki_page.reload.tag_name).to eq(tag.tag_name)
|
expect(wiki_page.reload.tag_name).to eq(tag.tag_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1170,14 +1174,17 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
expect(tag.name).to eq('put_renamed_tag')
|
expect(tag.name).to eq('put_renamed_tag')
|
||||||
expect(tag.category).to eq('meme')
|
expect(tag.category).to eq('meme')
|
||||||
|
|
||||||
expect(TagName.find_by(name: 'put_alias_a').canonical).to eq(tag.tag_name)
|
expect(TagName.find_by!(language_code: 'ja', name: 'put_alias_a'))
|
||||||
expect(TagName.find_by(name: 'put_alias_b').canonical).to eq(tag.tag_name)
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
|
expect(TagName.find_by!(language_code: 'ja', name: 'put_alias_b'))
|
||||||
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
|
|
||||||
old_name_alias = TagName.find_by(name: 'spec_tag')
|
old_name_alias = TagName.find_by(name: 'spec_tag')
|
||||||
expect(old_name_alias).to be_present
|
expect(old_name_alias).to be_present
|
||||||
expect(old_name_alias.canonical).to eq(tag.tag_name)
|
expect(old_name_alias).to have_attributes(
|
||||||
|
tag_id: tag.id, language_code: 'ja', primary_flg: false)
|
||||||
|
|
||||||
expect(alias_tn.reload.canonical).to be_nil
|
expect(alias_tn.reload.tag_id).to be_nil
|
||||||
|
|
||||||
expect(tag.parents.map(&:name)).to contain_exactly(
|
expect(tag.parents.map(&:name)).to contain_exactly(
|
||||||
'put_kept_parent',
|
'put_kept_parent',
|
||||||
@@ -1212,7 +1219,8 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
|
|
||||||
tag.reload
|
tag.reload
|
||||||
|
|
||||||
expect(TagName.find_by(name: 'put_alias_self_test').canonical).to eq(tag.tag_name)
|
expect(TagName.find_by!(language_code: 'ja', name: 'put_alias_self_test'))
|
||||||
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
expect(json['aliases']).to include('put_alias_self_test')
|
expect(json['aliases']).to include('put_alias_self_test')
|
||||||
expect(json['aliases']).not_to include('spec_tag')
|
expect(json['aliases']).not_to include('spec_tag')
|
||||||
end
|
end
|
||||||
@@ -1283,10 +1291,14 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
tag.reload
|
tag.reload
|
||||||
|
|
||||||
expect(tag.name).to eq('spec_tag')
|
expect(tag.name).to eq('spec_tag')
|
||||||
expect(TagName.find_by!(name: 'put_roundtrip_b').canonical).to eq(tag.tag_name)
|
expect(TagName.find_by!(language_code: 'ja', name: 'put_roundtrip_b'))
|
||||||
expect(tag.tag_name.aliases.map(&:name)).to contain_exactly('put_roundtrip_b', 'unko')
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
expect(tag.tag_name.aliases.map(&:name)).not_to include('spec_tag')
|
expect(TagName.where(tag_id: tag.id, language_code: 'ja', primary_flg: false).pluck(:name))
|
||||||
expect(alias_tn.reload.canonical).to eq(tag.tag_name)
|
.to contain_exactly('put_roundtrip_b', 'unko')
|
||||||
|
expect(TagName.where(tag_id: tag.id, language_code: 'ja', primary_flg: false).pluck(:name))
|
||||||
|
.not_to include('spec_tag')
|
||||||
|
expect(alias_tn.reload).to have_attributes(
|
||||||
|
tag_id: tag.id, language_code: 'ja', primary_flg: false)
|
||||||
|
|
||||||
version = tag.tag_versions.order(:version_no).last
|
version = tag.tag_versions.order(:version_no).last
|
||||||
|
|
||||||
@@ -1395,7 +1407,7 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'wiki を持つ tag を旧 alias へ戻しても wiki を新 canonical へ移す' do
|
it 'wiki を持つ tag を旧 alias へ戻しても wiki を新しい正本名へ移す' do
|
||||||
wiki_page =
|
wiki_page =
|
||||||
Wiki::Commit.create_content!(
|
Wiki::Commit.create_content!(
|
||||||
tag_name: tag.tag_name,
|
tag_name: tag.tag_name,
|
||||||
@@ -1429,7 +1441,8 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
|
|
||||||
expect(wiki_page.reload.tag_name).to eq(tag.tag_name)
|
expect(wiki_page.reload.tag_name).to eq(tag.tag_name)
|
||||||
expect(TagName.find_by!(name: 'put_wiki_roundtrip_b').wiki_page).to be_nil
|
expect(TagName.find_by!(name: 'put_wiki_roundtrip_b').wiki_page).to be_nil
|
||||||
expect(TagName.find_by!(name: 'put_wiki_roundtrip_b').canonical).to eq(tag.tag_name)
|
expect(TagName.find_by!(language_code: 'ja', name: 'put_wiki_roundtrip_b'))
|
||||||
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
|
|
||||||
versions = wiki_page.wiki_versions.order(:version_no).last(2)
|
versions = wiki_page.wiki_versions.order(:version_no).last(2)
|
||||||
|
|
||||||
@@ -1443,9 +1456,11 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
category: :general)
|
category: :general)
|
||||||
stolen_alias = create(:tag_name, :alias,
|
stolen_alias = create(:tag_name, :alias,
|
||||||
name: 'put_stolen_alias',
|
name: 'put_stolen_alias',
|
||||||
canonical: old_owner.tag_name)
|
tag: old_owner)
|
||||||
|
|
||||||
expect(old_owner.tag_name.aliases.map(&:name)).to include('put_stolen_alias')
|
expect(TagName.where(tag_id: old_owner.id, language_code: 'ja',
|
||||||
|
primary_flg: false).pluck(:name))
|
||||||
|
.to include('put_stolen_alias')
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
put "/tags/#{ tag.id }", params: {
|
put "/tags/#{ tag.id }", params: {
|
||||||
@@ -1461,8 +1476,11 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
expect(response).to have_http_status(:ok)
|
||||||
|
|
||||||
expect(stolen_alias.reload.canonical).to eq(tag.tag_name)
|
expect(stolen_alias.reload).to have_attributes(
|
||||||
expect(old_owner.reload.tag_name.aliases.map(&:name)).not_to include('put_stolen_alias')
|
tag_id: tag.id, language_code: 'ja', primary_flg: false)
|
||||||
|
expect(TagName.where(tag_id: old_owner.id, language_code: 'ja',
|
||||||
|
primary_flg: false).pluck(:name))
|
||||||
|
.not_to include('put_stolen_alias')
|
||||||
|
|
||||||
old_owner_versions = old_owner.tag_versions.order(:version_no)
|
old_owner_versions = old_owner.tag_versions.order(:version_no)
|
||||||
|
|
||||||
@@ -1479,7 +1497,7 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
category: :general)
|
category: :general)
|
||||||
stolen_alias = create(:tag_name, :alias,
|
stolen_alias = create(:tag_name, :alias,
|
||||||
name: 'put_alias_collision_name',
|
name: 'put_alias_collision_name',
|
||||||
canonical: old_owner.tag_name)
|
tag: old_owner)
|
||||||
wiki_page =
|
wiki_page =
|
||||||
Wiki::Commit.create_content!(
|
Wiki::Commit.create_content!(
|
||||||
tag_name: tag.tag_name,
|
tag_name: tag.tag_name,
|
||||||
@@ -1502,9 +1520,13 @@ RSpec.describe 'Tags API', type: :request do
|
|||||||
stolen_alias.reload
|
stolen_alias.reload
|
||||||
|
|
||||||
expect(tag.name).to eq('put_alias_collision_name')
|
expect(tag.name).to eq('put_alias_collision_name')
|
||||||
expect(stolen_alias.canonical_id).to be_nil
|
expect(stolen_alias).to have_attributes(
|
||||||
expect(TagName.find_by!(name: 'spec_tag').canonical).to eq(tag.tag_name)
|
tag_id: tag.id, language_code: 'ja', primary_flg: true)
|
||||||
expect(old_owner.tag_name.aliases.map(&:name)).not_to include('put_alias_collision_name')
|
expect(TagName.find_by!(language_code: 'ja', name: 'spec_tag'))
|
||||||
|
.to have_attributes(tag_id: tag.id, primary_flg: false)
|
||||||
|
expect(TagName.where(tag_id: old_owner.id, language_code: 'ja',
|
||||||
|
primary_flg: false).pluck(:name))
|
||||||
|
.not_to include('put_alias_collision_name')
|
||||||
|
|
||||||
old_owner_versions = old_owner.tag_versions.order(:version_no)
|
old_owner_versions = old_owner.tag_versions.order(:version_no)
|
||||||
|
|
||||||
|
|||||||
@@ -40,17 +40,16 @@ RSpec.describe PostCreatePlan do
|
|||||||
language_code: 'en', script_code: 'Latn')
|
language_code: 'en', script_code: 'Latn')
|
||||||
english = create(:tag, tag_name: english_name, category: :character)
|
english = create(:tag, tag_name: english_name, category: :character)
|
||||||
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
japanese_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: japanese.tag_name)
|
tag: japanese)
|
||||||
english_alias = create(:tag_name, :alias, name: 'temporary_alias',
|
english_alias = create(:tag_name, :alias, name: 'shared_alias',
|
||||||
canonical: english_name,
|
tag: english,
|
||||||
language_code: 'en', script_code: 'Latn')
|
language_code: 'en', script_code: 'Latn')
|
||||||
english_alias.update_columns(name: 'shared_alias')
|
|
||||||
|
|
||||||
expect(japanese_alias.reload).to have_attributes(
|
expect(japanese_alias.reload).to have_attributes(
|
||||||
canonical_id: japanese.tag_name_id, tag_id: japanese.id,
|
tag_id: japanese.id,
|
||||||
primary_flg: false, language_code: 'ja')
|
primary_flg: false, language_code: 'ja')
|
||||||
expect(english_alias.reload).to have_attributes(
|
expect(english_alias.reload).to have_attributes(
|
||||||
canonical_id: english_name.id, tag_id: english.id,
|
tag_id: english.id,
|
||||||
primary_flg: false, language_code: 'en')
|
primary_flg: false, language_code: 'en')
|
||||||
|
|
||||||
plan = described_class.new(attributes: { tags: 'shared_alias' }).build!(locale)
|
plan = described_class.new(attributes: { tags: 'shared_alias' }).build!(locale)
|
||||||
@@ -79,9 +78,9 @@ RSpec.describe PostCreatePlan do
|
|||||||
expect([TagName.count, Tag.count]).to eq(counts)
|
expect([TagName.count, Tag.count]).to eq(counts)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'resolves aliases and keeps tag sections separate from canonical names' do
|
it 'resolves aliases and keeps tag sections separate from primary names' do
|
||||||
canonical = create_tag!('虹夏', :character)
|
tag = create_tag!('虹夏', :character)
|
||||||
create(:tag_name, :alias, name: 'にじか', canonical: canonical.tag_name)
|
create(:tag_name, :alias, name: 'にじか', tag:)
|
||||||
create_tag!('動画', :meta)
|
create_tag!('動画', :meta)
|
||||||
|
|
||||||
plan = described_class.new(
|
plan = described_class.new(
|
||||||
|
|||||||
新しいイシューから参照
ユーザーをブロックする