このコミットが含まれているのは:
2026-09-27 23:55:19 +09:00
コミット 749d49327e
30個のファイルの変更、258行の追加、188行の削除
+1 -1
ファイルの表示
@@ -31,7 +31,7 @@ class MaterialVersionRecorder < VersionRecorder
{ url: @record.url,
parent: @record.parent,
tag: @record.tag,
tag_name: @record.tag&.name,
tag_name: @record.tag&.name('ja'),
tag_category: @record.tag&.category,
source_kind: @record.source_kind,
source_uri: @record.source_uri,
+1 -1
ファイルの表示
@@ -66,7 +66,7 @@ class PostBulkCreator
PostCreatePreflight.new(
attributes: attributes,
thumbnail: thumbnail_for(index, attributes),
host: @host).run
host: @host).run(locale)
if preflight[:existing_post_id].present?
return {
status: 'skipped',
+24 -17
ファイルの表示
@@ -12,8 +12,8 @@ class PostCreatePlan
direct_tag_specs, tag_sections = parse_direct_tag_specs(locale)
default_tag_specs = build_default_tag_specs(locale, direct_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] })
validate_new_tag_specs!(snapshot_tag_specs)
preload_existing_tags_by_name!(locale, snapshot_tag_specs.map { _1[:name] })
validate_new_tag_specs!(locale, snapshot_tag_specs)
post_tag_specs = expand_parent_tag_specs(locale, snapshot_tag_specs)
video_ms = normalise_video_ms(snapshot_tag_specs)
validate_video_sections!(video_ms, tag_sections)
@@ -49,7 +49,9 @@ class PostCreatePlan
tag_names.each do |raw_name|
tag_name, category, sections = parse_raw_tag_name(locale, raw_name)
existing_tag = existing_tags_by_name(locale)[tag_name]
raise Tag::DeprecatedTagNormalisationError, [existing_tag.name] if existing_tag&.deprecated?
if existing_tag&.deprecated?
raise Tag::DeprecatedTagNormalisationError, [existing_tag.name(locale.language_code)]
end
direct_tag_specs << {
name: tag_name,
@@ -106,17 +108,18 @@ class PostCreatePlan
default_tag_specs
end
def validate_new_tag_specs! specs
def validate_new_tag_specs! locale, specs
Array(specs).each do |spec|
next if existing_tags_by_name.key?(spec[:name])
next if existing_tags_by_name(locale).key?(spec[:name])
validate_new_tag_spec!(spec)
validate_new_tag_spec!(locale, spec)
end
end
def validate_new_tag_spec! spec
tag_name = TagName.new(name: spec[:name])
tag = Tag.new(category: spec[:category], tag_name:)
def validate_new_tag_spec! locale, spec
tag_name = TagName.new(name: spec[:name], language_code: locale.language_code,
script_code: locale.script_code, primary_flg: true)
tag = Tag.new(category: spec[:category])
return if tag_name.valid? && tag.valid?
post = Post.new
@@ -139,7 +142,7 @@ class PostCreatePlan
Tag.expand_parent_tags(existing_snapshot_tags)
.reject(&:deprecated?)
.map { |tag|
{ name: tag.name,
{ name: tag.name(locale.language_code),
category: tag.category.to_sym }
}
merge_tag_specs(snapshot_tag_specs + expanded_parent_specs)
@@ -161,7 +164,9 @@ class PostCreatePlan
def existing_tags_by_name locale
@existing_tags_by_name ||= begin
names = tag_names.map { canonical_tag_name_without_sections(locale, _1) }.uniq
Tag.joins(:tag_name).where(tag_names: { name: names }).index_by(&:name)
TagName.where(language_code: locale.language_code, primary_flg: true, name: names)
.includes(:tag)
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag }
end
end
@@ -171,9 +176,11 @@ class PostCreatePlan
return if missing_names.empty?
existing_tags_by_name(locale).merge!(
Tag.joins(:tag_name)
.where(tag_names: { name: missing_names })
.index_by(&:name))
TagName.where(language_code: locale.language_code,
primary_flg: true,
name: missing_names)
.includes(:tag)
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag })
end
def canonical_tag_name_without_sections locale, raw_name
@@ -266,8 +273,8 @@ class PostCreatePlan
tag_name = TagName.find_by(language_code: locale.language_code, name:)
return name if !(tag_name) || tag_name.primary?
TagName.find_by!(language_code: locale.language_code,
tag_id: tag_name.tag_id,
primary_flg: true).name
TagName.find_by(language_code: locale.language_code,
tag_id: tag_name.tag_id,
primary_flg: true)&.name || name
end
end
+2 -2
ファイルの表示
@@ -15,7 +15,7 @@ class PostCreatePreflight
@host = host
end
def run
def run locale
preview = PostImportPreviewer.new.preview_rows(
rows: [preview_row],
fetch_metadata: false).first
@@ -53,7 +53,7 @@ class PostCreatePreflight
original_created_from: preview[:attributes]['original_created_from'],
original_created_before: preview[:attributes]['original_created_before'],
duration: preview[:attributes]['duration'],
video_ms: preview[:attributes]['video_ms'] }).build!
video_ms: preview[:attributes]['video_ms'] }).build!(locale)
{
url: plan[:url],
+13 -8
ファイルの表示
@@ -24,7 +24,10 @@ class PostCreator
snapshot_tags = planned_snapshot_tags(locale)
post_tags = planned_post_tags(locale)
sections = planned_sections(locale)
TagVersioning.record_tag_snapshots!(snapshot_tags, created_by_user: @actor)
TagVersioning.record_tag_snapshots!(
snapshot_tags,
created_by_user: @actor,
language_code: locale.language_code)
post.video_ms = planned_video_ms(locale)
post.save!
sync_post_tags!(post, post_tags, sections)
@@ -70,7 +73,8 @@ class PostCreator
tag_sections: materialise_sections(
@attributes[:tag_sections] || { },
snapshot_tags,
post_tags),
post_tags,
locale),
normalised_parent_post_ids: @attributes[:normalised_parent_post_ids] || [],
video_ms: @attributes[:video_ms] }
else
@@ -81,15 +85,16 @@ class PostCreator
def build_materialised_plan locale
plan = PostCreatePlan.new(attributes: @attributes).build!(locale)
snapshot_tags = materialise_tags(plan[:snapshot_tag_specs] || [])
post_tags = materialise_tags(plan[:post_tag_specs] || [])
snapshot_tags = materialise_tags(locale, plan[:snapshot_tag_specs] || [])
post_tags = materialise_tags(locale, plan[:post_tag_specs] || [])
{
snapshot_tags: snapshot_tags,
post_tags: post_tags,
tag_sections: materialise_sections(
plan[:tag_sections] || { },
snapshot_tags,
post_tags),
post_tags,
locale),
normalised_parent_post_ids: plan[:normalised_parent_post_ids] || [],
video_ms: plan[:video_ms] }
end
@@ -106,10 +111,10 @@ class PostCreator
end.values
end
def materialise_sections sections_by_name, snapshot_tags, post_tags
tags_by_name = post_tags.index_by(&:name)
def materialise_sections sections_by_name, snapshot_tags, post_tags, locale = Locale.nipponese
tags_by_name = post_tags.index_by { _1.name(locale.language_code) }
snapshot_tags.each do |tag|
tags_by_name[tag.name] ||= tag
tags_by_name[tag.name(locale.language_code)] ||= tag
end
sections_by_name.each_with_object({ }) do |(tag_name, ranges), sections|
+16 -13
ファイルの表示
@@ -16,7 +16,7 @@ class PostImportPreviewer
THUMBNAIL_FETCH_WARNING = 'サムネールを取得できませんでした.'.freeze
METADATA_FETCH_WARNING = '自動取得に失敗しました.'.freeze
def preview_rows rows:, fetch_metadata: true, metadata_cache: { }
def preview_rows locale, rows:, fetch_metadata: true, metadata_cache: { }
prepared_rows = rows.map { prepare_row(_1) }
url_counts = prepared_rows.filter_map { _1[:normal_url] }.tally
existing_posts =
@@ -36,7 +36,7 @@ class PostImportPreviewer
existing_posts,
url_counts)
prepared_rows.map { |row|
preview_row(row,
preview_row(locale, row,
fetch_metadata:,
metadata_cache:,
existing_posts:,
@@ -59,7 +59,7 @@ class PostImportPreviewer
source.merge(url_text: url, normal_url:, url_error: validate_url_safety(normal_url))
end
def preview_row row,
def preview_row locale, row,
fetch_metadata:,
metadata_cache:,
existing_posts:,
@@ -124,7 +124,8 @@ class PostImportPreviewer
attributes['url'] = url
validate_basic_data(attributes, validation_errors)
validate_preview_tags(merged_tags(tag_sources, provenance['tags']),
validate_preview_tags(locale,
merged_tags(tag_sources, provenance['tags']),
validation_errors,
known_tags)
validate_parents(attributes['parent_post_ids'], validation_errors, existing_parent_ids)
@@ -362,11 +363,9 @@ class PostImportPreviewer
}.compact.uniq
return { } if names.empty?
Tag.joins(:tag_name)
.where(tag_names: { name: names })
.includes(:tag_name)
.to_a
.index_by(&:name)
TagName.where(language_code: 'ja', primary_flg: true, name: names)
.includes(:tag)
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag }
end
def preload_parent_ids prepared_rows
@@ -437,19 +436,21 @@ class PostImportPreviewer
sources['automatic'].to_s
end
def preview_tag_names raw
def preview_tag_names locale, raw
names = raw.to_s.split
return [] if names.empty?
if names.any? { _1.downcase.start_with?('nico:') }
return []
end
names.map { |name| TagName.canonicalise(name.sub(/\[.*\]\z/, '')).first }
names.map { |name|
TagName.canonicalise(locale, name.sub(/\[.*\]\z/, '')).first
}
rescue Tag::SectionLiteralParseError
[]
end
def validate_preview_tags raw, errors, known_tags
def validate_preview_tags locale, raw, errors, known_tags
names = raw.to_s.split
return if names.empty?
if names.any? { _1.downcase.start_with?('nico:') }
@@ -457,7 +458,9 @@ class PostImportPreviewer
return
end
parsed = names.map { |name| TagName.canonicalise(name.sub(/\[.*\]\z/, '')).first }
parsed = names.map { |name|
TagName.canonicalise(locale, name.sub(/\[.*\]\z/, '')).first
}
existing = parsed.filter_map { known_tags[_1] }
deprecated = existing.select(&:deprecated?).map(&:name)
errors[:tags] = ["廃止済みタグがあります: #{ deprecated.join(' ') }"] if deprecated.present?
+3 -3
ファイルの表示
@@ -47,9 +47,9 @@ class PostMetadataFetcher
existing_tags =
Tag
.joins(:tag_name)
.where(tag_names: { name: names })
.index_by(&:name)
.joins(:tag_names)
.where(tag_names: { language_code: 'ja', primary_flg: true, name: names })
.index_by { _1.name('ja') }
names.map { |name|
tag = existing_tags[name]
+6 -5
ファイルの表示
@@ -1,10 +1,11 @@
class TagVersionRecorder < VersionRecorder
def self.record! tag:, event_type:, created_by_user:
new(tag:, event_type:, created_by_user:).record!
def self.record! tag:, event_type:, created_by_user:, language_code: 'ja'
new(tag:, event_type:, created_by_user:, language_code:).record!
end
def initialize tag:, event_type:, created_by_user:
def initialize tag:, event_type:, created_by_user:, language_code:
super(record: tag, event_type:, created_by_user:)
@language_code = language_code
end
private
@@ -14,10 +15,10 @@ class TagVersionRecorder < VersionRecorder
def record_key = :tag
def snapshot_attributes
{ name: @record.name,
{ name: @record.name(@language_code),
category: @record.category,
deprecated_at: @record.deprecated_at,
aliases: @record.snapshot_aliases.join(' '),
aliases: @record.snapshot_aliases(@language_code).join(' '),
parent_tag_ids: @record.snapshot_parent_tag_ids.join(' ') }
end
end
+8 -8
ファイルの表示
@@ -1,22 +1,22 @@
class TagVersioning
def self.record! tag, event_type:, created_by_user:
TagVersionRecorder.record!(tag:, event_type:, created_by_user:)
def self.record! tag, event_type:, created_by_user:, language_code: 'ja'
TagVersionRecorder.record!(tag:, event_type:, created_by_user:, language_code:)
end
def self.ensure_snapshot! tag, created_by_user:
def self.ensure_snapshot! tag, created_by_user:, language_code: 'ja'
return if tag.tag_versions.exists?
TagVersionRecorder.record!(tag:, event_type: :create, created_by_user:)
TagVersionRecorder.record!(tag:, event_type: :create, created_by_user:, language_code:)
end
def self.record_tag_snapshot! tag, created_by_user:
def self.record_tag_snapshot! tag, created_by_user:, language_code: 'ja'
event_type = tag.tag_versions.exists? ? :update : :create
record!(tag, event_type:, created_by_user:)
record!(tag, event_type:, created_by_user:, language_code:)
end
def self.record_tag_snapshots! tags, created_by_user:
def self.record_tag_snapshots! tags, created_by_user:, language_code: 'ja'
tags.each do |tag|
record_tag_snapshot!(tag, created_by_user:)
record_tag_snapshot!(tag, created_by_user:, language_code:)
end
end
end
+3 -3
ファイルの表示
@@ -41,7 +41,7 @@ class TheatrePostSelector
def weighted_candidates
@weighted_candidates ||= begin
penalties = tag_penalties
posts = eligible_posts.includes(tags: :tag_name).to_a
posts = eligible_posts.includes(tags: :tag_names).to_a
posts.map do |post|
post_tags = post.tags.to_a
@@ -82,7 +82,7 @@ class TheatrePostSelector
def tag_penalty_json
return [] if tag_penalties.empty?
tags = Tag.where(id: tag_penalties.keys).includes(:tag_name).index_by(&:id)
tags = Tag.where(id: tag_penalties.keys).includes(:tag_names).index_by(&:id)
tag_penalties
.map { |tag_id, penalty|
@@ -113,7 +113,7 @@ class TheatrePostSelector
def light_tag_json tag
{ id: tag.id,
name: tag.name,
name: tag.name('ja'),
category: tag.category }
end
end