このコミットが含まれているのは:
@@ -1,5 +1,7 @@
|
|||||||
class DeerjikistsController < ApplicationController
|
class DeerjikistsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
platform = params[:platform].to_s.strip
|
platform = params[:platform].to_s.strip
|
||||||
code = params[:code].to_s.strip
|
code = params[:code].to_s.strip
|
||||||
return render_bad_request('platform は必須です.') if platform.blank?
|
return render_bad_request('platform は必須です.') if platform.blank?
|
||||||
@@ -10,7 +12,7 @@ class DeerjikistsController < ApplicationController
|
|||||||
.includes(tag: :tag_names)
|
.includes(tag: :tag_names)
|
||||||
.find_by(platform:, code:)
|
.find_by(platform:, code:)
|
||||||
if deerjikist
|
if deerjikist
|
||||||
render json: DeerjikistRepr.base(deerjikist)
|
render json: DeerjikistRepr.base(deerjikist, language_code: locale.language_code)
|
||||||
else
|
else
|
||||||
head :not_found
|
head :not_found
|
||||||
end
|
end
|
||||||
@@ -20,6 +22,7 @@ class DeerjikistsController < 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!
|
||||||
platform = params[:platform].to_s.strip
|
platform = params[:platform].to_s.strip
|
||||||
code = params[:code].to_s.strip
|
code = params[:code].to_s.strip
|
||||||
tag_id = params[:tag_id].to_i
|
tag_id = params[:tag_id].to_i
|
||||||
@@ -32,7 +35,7 @@ class DeerjikistsController < ApplicationController
|
|||||||
d.save!
|
d.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: DeerjikistRepr.base(deerjikist)
|
render json: DeerjikistRepr.base(deerjikist, language_code: locale.language_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ class MaterialsController < ApplicationController
|
|||||||
rescue_from MaterialZipExporter::MissingFileError, with: :render_zip_missing_file
|
rescue_from MaterialZipExporter::MissingFileError, with: :render_zip_missing_file
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
page = (params[:page].presence || 1).to_i
|
page = (params[:page].presence || 1).to_i
|
||||||
limit = (params[:limit].presence || 20).to_i
|
limit = (params[:limit].presence || 20).to_i
|
||||||
|
|
||||||
@@ -42,7 +44,10 @@ class MaterialsController < ApplicationController
|
|||||||
.offset(offset)
|
.offset(offset)
|
||||||
.to_a
|
.to_a
|
||||||
|
|
||||||
response = { materials: MaterialRepr.list_many(materials, host: request.base_url),
|
response = { materials: MaterialRepr.list_many(
|
||||||
|
materials,
|
||||||
|
host: request.base_url,
|
||||||
|
language_code: locale.language_code),
|
||||||
count: }
|
count: }
|
||||||
if filters[:tag_id]
|
if filters[:tag_id]
|
||||||
response[:tag_scope] = material_index_tag_scope(filters, tag_graph)
|
response[:tag_scope] = material_index_tag_scope(filters, tag_graph)
|
||||||
@@ -55,6 +60,8 @@ class MaterialsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
material =
|
material =
|
||||||
Material
|
Material
|
||||||
.includes(:tag, :material_export_items)
|
.includes(:tag, :material_export_items)
|
||||||
@@ -65,7 +72,8 @@ class MaterialsController < ApplicationController
|
|||||||
|
|
||||||
wiki_page_body = material.tag&.tag_name('ja')&.wiki_page&.current_revision&.body
|
wiki_page_body = material.tag&.tag_name('ja')&.wiki_page&.current_revision&.body
|
||||||
|
|
||||||
render json: MaterialRepr.base(material, host: request.base_url).merge(wiki_page_body:)
|
render json: MaterialRepr.base(material, host: request.base_url,
|
||||||
|
language_code: locale.language_code).merge(wiki_page_body:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -109,7 +117,8 @@ class MaterialsController < ApplicationController
|
|||||||
|
|
||||||
if material
|
if material
|
||||||
log_thumbnail_generation(material, MaterialThumbnailGenerator.generate!(material))
|
log_thumbnail_generation(material, MaterialThumbnailGenerator.generate!(material))
|
||||||
render json: MaterialRepr.base(material, host: request.base_url), status: :created
|
render json: MaterialRepr.base(material, host: request.base_url,
|
||||||
|
language_code: locale.language_code), status: :created
|
||||||
else
|
else
|
||||||
render_validation_error material
|
render_validation_error material
|
||||||
end
|
end
|
||||||
@@ -162,7 +171,8 @@ class MaterialsController < ApplicationController
|
|||||||
|
|
||||||
log_thumbnail_generation(material, MaterialThumbnailGenerator.generate!(material))
|
log_thumbnail_generation(material, MaterialThumbnailGenerator.generate!(material))
|
||||||
|
|
||||||
render json: MaterialRepr.base(material, host: request.base_url)
|
render json: MaterialRepr.base(material, host: request.base_url,
|
||||||
|
language_code: locale.language_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
class NicoTagsController < ApplicationController
|
class NicoTagsController < ApplicationController
|
||||||
def index
|
def index
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
name = params[:name].presence
|
name = params[:name].presence
|
||||||
linked_tag = params[:linked_tag].presence
|
linked_tag = params[:linked_tag].presence
|
||||||
link_status = params[:link_status].presence
|
link_status = params[:link_status].presence
|
||||||
@@ -68,7 +70,9 @@ class NicoTagsController < ApplicationController
|
|||||||
render json: { tags: tags.map { |tag|
|
render json: { tags: tags.map { |tag|
|
||||||
external_tag_json(tag).merge(
|
external_tag_json(tag).merge(
|
||||||
recent_post_tag_created_at: tag.recent_post_tag_created_at,
|
recent_post_tag_created_at: tag.recent_post_tag_created_at,
|
||||||
linked_tags: tag.linked_tags.map { |lt| TagRepr.base(lt) })
|
linked_tags: tag.linked_tags.map { |lt|
|
||||||
|
TagRepr.base(lt, language_code: locale.language_code)
|
||||||
|
})
|
||||||
}, count: }
|
}, count: }
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -109,7 +113,9 @@ class NicoTagsController < ApplicationController
|
|||||||
created_by_user: current_user)
|
created_by_user: current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: tag.linked_tags.map { |t| TagRepr.base(t) }, status: :ok
|
render json: tag.linked_tags.map { |t|
|
||||||
|
TagRepr.base(t, language_code: locale.language_code)
|
||||||
|
}, status: :ok
|
||||||
rescue Tag::NicoTagNormalisationError
|
rescue Tag::NicoTagNormalisationError
|
||||||
render_validation_error fields: { tags: ['ニコニコ・タグ同士は連携できません.'] }
|
render_validation_error fields: { tags: ['ニコニコ・タグ同士は連携できません.'] }
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ class PostsController < ApplicationController
|
|||||||
q = q.except(:select, :order)
|
q = q.except(:select, :order)
|
||||||
|
|
||||||
render json: { posts: posts.map { |post|
|
render json: { posts: posts.map { |post|
|
||||||
PostRepr.base(post).merge(updated_at: post.updated_at_all).tap do |json|
|
PostRepr.base(post, language_code: locale.language_code)
|
||||||
|
.merge(updated_at: post.updated_at_all).tap do |json|
|
||||||
json['thumbnail'] =
|
json['thumbnail'] =
|
||||||
if post.thumbnail.attached?
|
if post.thumbnail.attached?
|
||||||
rails_storage_proxy_url(post.thumbnail, only_path: false)
|
rails_storage_proxy_url(post.thumbnail, only_path: false)
|
||||||
@@ -116,7 +117,7 @@ class PostsController < ApplicationController
|
|||||||
.first
|
.first
|
||||||
return head :not_found unless post
|
return head :not_found unless post
|
||||||
|
|
||||||
render json: PostRepr.base(post, current_user)
|
render json: PostRepr.base(post, current_user, language_code: locale.language_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def metadata
|
def metadata
|
||||||
@@ -191,6 +192,8 @@ class PostsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
locale = resolve_locale!
|
||||||
|
|
||||||
post =
|
post =
|
||||||
Post
|
Post
|
||||||
.includes(:uploaded_user, :parents, :children,
|
.includes(:uploaded_user, :parents, :children,
|
||||||
@@ -209,8 +212,9 @@ class PostsController < ApplicationController
|
|||||||
parent_posts:,
|
parent_posts:,
|
||||||
child_posts:,
|
child_posts:,
|
||||||
sibling_posts:,
|
sibling_posts:,
|
||||||
related:)
|
related:,
|
||||||
.merge(tags: build_tag_tree_for(post))
|
language_code: locale.language_code)
|
||||||
|
.merge(tags: build_tag_tree_for(post, locale.language_code))
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -251,7 +255,7 @@ class PostsController < ApplicationController
|
|||||||
thumbnail: params[:thumbnail])).create!(locale)
|
thumbnail: params[:thumbnail])).create!(locale)
|
||||||
|
|
||||||
post.reload
|
post.reload
|
||||||
render json: PostRepr.base(post), status: :created
|
render json: PostRepr.base(post, language_code: locale.language_code), status: :created
|
||||||
rescue PostCreatePreflight::ValidationFailed => e
|
rescue PostCreatePreflight::ValidationFailed => e
|
||||||
render_validation_error fields: e.fields, base: e.base_errors
|
render_validation_error fields: e.fields, base: e.base_errors
|
||||||
rescue Tag::NicoTagNormalisationError
|
rescue Tag::NicoTagNormalisationError
|
||||||
@@ -379,8 +383,8 @@ class PostsController < ApplicationController
|
|||||||
return render json: conflict_json, status: :conflict if conflict_json
|
return render json: conflict_json, status: :conflict if conflict_json
|
||||||
|
|
||||||
post.reload
|
post.reload
|
||||||
json = PostRepr.base(post, current_user)
|
json = PostRepr.base(post, current_user, language_code: locale.language_code)
|
||||||
json['tags'] = build_tag_tree_for(post)
|
json['tags'] = build_tag_tree_for(post, locale.language_code)
|
||||||
render json:, status: :ok
|
render json:, status: :ok
|
||||||
rescue Tag::NicoTagNormalisationError
|
rescue Tag::NicoTagNormalisationError
|
||||||
render_validation_error fields: { tags: ['ニコニコ・タグは直接指定できません.'] }
|
render_validation_error fields: { tags: ['ニコニコ・タグは直接指定できません.'] }
|
||||||
@@ -487,7 +491,7 @@ class PostsController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_tag_tree_for post
|
def build_tag_tree_for post, language_code = 'ja'
|
||||||
post_tags = post.post_tags.reject { |post_tag| post_tag.tag.deprecated? }
|
post_tags = post.post_tags.reject { |post_tag| post_tag.tag.deprecated? }
|
||||||
tags = post_tags.map(&:tag)
|
tags = post_tags.map(&:tag)
|
||||||
tag_ids = tags.map(&:id)
|
tag_ids = tags.map(&:id)
|
||||||
@@ -517,7 +521,7 @@ class PostsController < ApplicationController
|
|||||||
sections = sections_by_tag_id.fetch(tag_id, [])
|
sections = sections_by_tag_id.fetch(tag_id, [])
|
||||||
|
|
||||||
if path.include?(tag_id)
|
if path.include?(tag_id)
|
||||||
return TagRepr.inline(tag).merge(children: [], sections:)
|
return TagRepr.inline(tag, language_code:).merge(children: [], sections:)
|
||||||
end
|
end
|
||||||
|
|
||||||
if memo.key?(tag_id)
|
if memo.key?(tag_id)
|
||||||
@@ -529,7 +533,7 @@ class PostsController < ApplicationController
|
|||||||
|
|
||||||
children = child_ids.filter_map { |cid| build_node.(cid, new_path) }
|
children = child_ids.filter_map { |cid| build_node.(cid, new_path) }
|
||||||
|
|
||||||
memo[tag_id] = TagRepr.inline(tag).merge(children:, sections:)
|
memo[tag_id] = TagRepr.inline(tag, language_code:).merge(children:, sections:)
|
||||||
end
|
end
|
||||||
|
|
||||||
internal_tags = root_ids.filter_map { |id| build_node.call(id, []) }
|
internal_tags = root_ids.filter_map { |id| build_node.call(id, []) }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
class TagVersionsController < ApplicationController
|
class TagVersionsController < ApplicationController
|
||||||
def index
|
def index
|
||||||
|
locale = resolve_locale!
|
||||||
tag_id = params[:id].presence
|
tag_id = params[:id].presence
|
||||||
page = (params[:page].presence || 1).to_i
|
page = (params[:page].presence || 1).to_i
|
||||||
limit = (params[:limit].presence || 20).to_i
|
limit = (params[:limit].presence || 20).to_i
|
||||||
@@ -27,12 +28,12 @@ class TagVersionsController < ApplicationController
|
|||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
|
|
||||||
render json: { versions: serialise_versions(versions), count: }
|
render json: { versions: serialise_versions(versions, locale.language_code), count: }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def serialise_versions rows
|
def serialise_versions rows, language_code
|
||||||
user_ids = rows.map(&:created_by_user_id).compact.uniq
|
user_ids = rows.map(&:created_by_user_id).compact.uniq
|
||||||
users_by_id = User.where(id: user_ids).pluck(:id, :name).to_h
|
users_by_id = User.where(id: user_ids).pluck(:id, :name).to_h
|
||||||
|
|
||||||
@@ -54,13 +55,14 @@ class TagVersionsController < ApplicationController
|
|||||||
parent_tags =
|
parent_tags =
|
||||||
build_version_values(cur_parent_tag_ids, prev_parent_tag_ids, key: :tag_id)
|
build_version_values(cur_parent_tag_ids, prev_parent_tag_ids, key: :tag_id)
|
||||||
.map do |h|
|
.map do |h|
|
||||||
{ tag: TagRepr.base(tags_by_id[h[:tag_id]]),
|
{ tag: TagRepr.base(tags_by_id[h[:tag_id]], language_code:),
|
||||||
type: h[:type] }
|
type: h[:type] }
|
||||||
end
|
end
|
||||||
|
|
||||||
{ tag_id: row.tag_id,
|
{ tag_id: row.tag_id,
|
||||||
version_no: row.version_no,
|
version_no: row.version_no,
|
||||||
event_type: row.event_type,
|
event_type: row.event_type,
|
||||||
|
names: row.names,
|
||||||
name: { current: row.name, prev: row.attributes['prev_name'] },
|
name: { current: row.name, prev: row.attributes['prev_name'] },
|
||||||
category: { current: row.category, prev: row.attributes['prev_category'] },
|
category: { current: row.category, prev: row.attributes['prev_category'] },
|
||||||
deprecated_at: { current: row.deprecated_at&.iso8601,
|
deprecated_at: { current: row.deprecated_at&.iso8601,
|
||||||
|
|||||||
@@ -198,7 +198,8 @@ class TagsController < ApplicationController
|
|||||||
parent_tag_id = nil if parent_tag_id <= 0
|
parent_tag_id = nil if parent_tag_id <= 0
|
||||||
material_filter = material_filter_param(default: 'any')
|
material_filter = material_filter_param(default: 'any')
|
||||||
|
|
||||||
graph = build_with_depth_graph(material_filter)
|
locale = resolve_locale!
|
||||||
|
graph = build_with_depth_graph(material_filter, locale.language_code)
|
||||||
|
|
||||||
tag_ids =
|
tag_ids =
|
||||||
if parent_tag_id
|
if parent_tag_id
|
||||||
@@ -325,7 +326,9 @@ class TagsController < ApplicationController
|
|||||||
return head :not_found unless tag
|
return head :not_found unless tag
|
||||||
|
|
||||||
render json: { tag: TagRepr.base(tag, language_code: locale.language_code),
|
render json: { tag: TagRepr.base(tag, language_code: locale.language_code),
|
||||||
deerjikists: DeerjikistRepr.many(tag.deerjikists) }
|
deerjikists: DeerjikistRepr.many(
|
||||||
|
tag.deerjikists,
|
||||||
|
language_code: locale.language_code) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def deerjikists_by_name
|
def deerjikists_by_name
|
||||||
@@ -342,7 +345,9 @@ class TagsController < ApplicationController
|
|||||||
return head :not_found unless tag
|
return head :not_found unless tag
|
||||||
|
|
||||||
render json: { tag: TagRepr.base(tag, language_code: locale.language_code),
|
render json: { tag: TagRepr.base(tag, language_code: locale.language_code),
|
||||||
deerjikists: DeerjikistRepr.many(tag.deerjikists) }
|
deerjikists: DeerjikistRepr.many(
|
||||||
|
tag.deerjikists,
|
||||||
|
language_code: locale.language_code) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_deerjikists
|
def update_deerjikists
|
||||||
@@ -404,7 +409,8 @@ class TagsController < ApplicationController
|
|||||||
|
|
||||||
return if performed?
|
return if performed?
|
||||||
|
|
||||||
render json: DeerjikistRepr.many(tag.reload.deerjikists)
|
render json: DeerjikistRepr.many(tag.reload.deerjikists,
|
||||||
|
language_code: locale.language_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def materials_by_name
|
def materials_by_name
|
||||||
@@ -422,7 +428,7 @@ class TagsController < ApplicationController
|
|||||||
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
|
.find_by(tag_names: { name:, language_code: locale.language_code, primary_flg: true })
|
||||||
return head :not_found unless tag
|
return head :not_found unless tag
|
||||||
|
|
||||||
graph = build_with_depth_graph(material_filter)
|
graph = build_with_depth_graph(material_filter, locale.language_code)
|
||||||
|
|
||||||
render json: build_tag_children(tag, graph:, language_code: locale.language_code)
|
render json: build_tag_children(tag, graph:, language_code: locale.language_code)
|
||||||
end
|
end
|
||||||
@@ -543,9 +549,7 @@ class TagsController < ApplicationController
|
|||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_with_depth_graph material_filter
|
def build_with_depth_graph material_filter, language_code
|
||||||
locale = resolve_locale!
|
|
||||||
|
|
||||||
children_by_parent_id = Hash.new { |h, k| h[k] = [] }
|
children_by_parent_id = Hash.new { |h, k| h[k] = [] }
|
||||||
parent_ids_by_child_id = Hash.new { |h, k| h[k] = [] }
|
parent_ids_by_child_id = Hash.new { |h, k| h[k] = [] }
|
||||||
|
|
||||||
@@ -564,7 +568,7 @@ class TagsController < ApplicationController
|
|||||||
Tag
|
Tag
|
||||||
.joins(:tag_names)
|
.joins(:tag_names)
|
||||||
.where(id: tag_ids,
|
.where(id: tag_ids,
|
||||||
tag_names: { language_code: locale.language_code, primary_flg: true })
|
tag_names: { language_code:, primary_flg: true })
|
||||||
.pluck('tags.id', 'tag_names.name', 'tags.category', 'tags.deprecated_at')
|
.pluck('tags.id', 'tag_names.name', 'tags.category', 'tags.deprecated_at')
|
||||||
.each_with_object({ }) do |(id, name, category, deprecated_at), h|
|
.each_with_object({ }) do |(id, name, category, deprecated_at), h|
|
||||||
h[id] = { name:, category:, deprecated: deprecated_at.present?,
|
h[id] = { name:, category:, deprecated: deprecated_at.present?,
|
||||||
@@ -712,7 +716,10 @@ class TagsController < ApplicationController
|
|||||||
TagRepr.base(tag, language_code:).merge(
|
TagRepr.base(tag, language_code:).merge(
|
||||||
children: children.map { build_tag_children(_1, graph:, language_code:) },
|
children: children.map { build_tag_children(_1, graph:, language_code:) },
|
||||||
has_material: tag_graph ? tag_graph[:has_material] : material.present?,
|
has_material: tag_graph ? tag_graph[:has_material] : material.present?,
|
||||||
material: material && MaterialRepr.base(material, host: request.base_url))
|
material: material && MaterialRepr.base(
|
||||||
|
material,
|
||||||
|
host: request.base_url,
|
||||||
|
language_code:))
|
||||||
end
|
end
|
||||||
|
|
||||||
def record_tag_version! tag, event_type:, created_by_user:, language_code: 'ja',
|
def record_tag_version! tag, event_type:, created_by_user:, language_code: 'ja',
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ class TagVersion < ApplicationRecord
|
|||||||
meta: 'meta' }, validate: true
|
meta: 'meta' }, validate: true
|
||||||
|
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
|
validates :names, presence: true
|
||||||
validates :category, presence: true
|
validates :category, presence: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ module DeerjikistRepr
|
|||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def base deerjikist
|
def base deerjikist, language_code: 'ja'
|
||||||
deerjikist.as_json(BASE).merge(
|
deerjikist.as_json(BASE).merge(
|
||||||
tag: deerjikist.tag && TagRepr.base(deerjikist.tag, language_code: 'ja'))
|
tag: deerjikist.tag && TagRepr.base(deerjikist.tag, language_code:))
|
||||||
end
|
end
|
||||||
|
|
||||||
def many deerjikists
|
def many deerjikists, language_code: 'ja'
|
||||||
deerjikists.map { |d| base(d) }
|
deerjikists.map { |d| base(d, language_code:) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ module MaterialRepr
|
|||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def base material, host:
|
def base material, host:, language_code: 'ja'
|
||||||
material.as_json(BASE).merge(
|
material.as_json(BASE).merge(
|
||||||
tag: material.tag && TagRepr.base(material.tag, language_code: 'ja'),
|
tag: material.tag && TagRepr.base(material.tag, language_code:),
|
||||||
file: if material.file.attached?
|
file: if material.file.attached?
|
||||||
Rails.application.routes.url_helpers.rails_storage_proxy_url(
|
Rails.application.routes.url_helpers.rails_storage_proxy_url(
|
||||||
material.file, host:)
|
material.file, host:)
|
||||||
end,
|
end,
|
||||||
thumbnail: thumbnail_url(material, host:),
|
thumbnail: thumbnail_url(material, host:),
|
||||||
thumbnail_fallback_text: thumbnail_fallback_text(material),
|
thumbnail_fallback_text: thumbnail_fallback_text(material, language_code:),
|
||||||
thumbnail_fallback_kind: thumbnail_fallback_kind(material),
|
thumbnail_fallback_kind: thumbnail_fallback_kind(material),
|
||||||
media_kind: media_kind(material),
|
media_kind: media_kind(material),
|
||||||
file_byte_size: material.file_byte_size,
|
file_byte_size: material.file_byte_size,
|
||||||
@@ -28,11 +28,11 @@ module MaterialRepr
|
|||||||
export_items: export_items(material))
|
export_items: export_items(material))
|
||||||
end
|
end
|
||||||
|
|
||||||
def many materials, host:
|
def many materials, host:, language_code: 'ja'
|
||||||
materials.map { |m| base(m, host:) }
|
materials.map { |m| base(m, host:, language_code:) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def list material, host:
|
def list material, host:, language_code: 'ja'
|
||||||
{ id: material.id,
|
{ id: material.id,
|
||||||
version_no: material.version_no,
|
version_no: material.version_no,
|
||||||
url: material.url,
|
url: material.url,
|
||||||
@@ -41,9 +41,9 @@ module MaterialRepr
|
|||||||
source_path: material.source_path,
|
source_path: material.source_path,
|
||||||
source_file_id: material.source_file_id,
|
source_file_id: material.source_file_id,
|
||||||
normalized_source_key: material.normalized_source_key,
|
normalized_source_key: material.normalized_source_key,
|
||||||
tag: compact_tag(material.tag),
|
tag: compact_tag(material.tag, language_code:),
|
||||||
thumbnail: thumbnail_url(material, host:),
|
thumbnail: thumbnail_url(material, host:),
|
||||||
thumbnail_fallback_text: thumbnail_fallback_text(material),
|
thumbnail_fallback_text: thumbnail_fallback_text(material, language_code:),
|
||||||
thumbnail_fallback_kind: thumbnail_fallback_kind(material),
|
thumbnail_fallback_kind: thumbnail_fallback_kind(material),
|
||||||
media_kind: media_kind(material),
|
media_kind: media_kind(material),
|
||||||
content_type: material.content_type,
|
content_type: material.content_type,
|
||||||
@@ -54,8 +54,8 @@ module MaterialRepr
|
|||||||
export_items: export_items(material) }
|
export_items: export_items(material) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_many materials, host:
|
def list_many materials, host:, language_code: 'ja'
|
||||||
materials.map { |m| list(m, host:) }
|
materials.map { |m| list(m, host:, language_code:) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_paths material
|
def export_paths material
|
||||||
@@ -80,8 +80,8 @@ module MaterialRepr
|
|||||||
material.thumbnail, host:)
|
material.thumbnail, host:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def thumbnail_fallback_text material
|
def thumbnail_fallback_text material, language_code:
|
||||||
material.tag&.name('ja') || material.created_at&.strftime('%Y-%m-%d')
|
material.tag&.name(language_code) || material.created_at&.strftime('%Y-%m-%d')
|
||||||
end
|
end
|
||||||
|
|
||||||
def thumbnail_fallback_kind material
|
def thumbnail_fallback_kind material
|
||||||
@@ -99,11 +99,11 @@ module MaterialRepr
|
|||||||
'file_other'
|
'file_other'
|
||||||
end
|
end
|
||||||
|
|
||||||
def compact_tag tag
|
def compact_tag tag, language_code:
|
||||||
return nil unless tag
|
return nil unless tag
|
||||||
|
|
||||||
{ id: tag.id,
|
{ id: tag.id,
|
||||||
name: tag.name('ja'),
|
name: tag.name(language_code),
|
||||||
category: tag.category,
|
category: tag.category,
|
||||||
deprecated_at: tag.deprecated_at }
|
deprecated_at: tag.deprecated_at }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,23 +17,23 @@ module PostRepr
|
|||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def base post, current_user = nil, host: nil
|
def base post, current_user = nil, host: nil, language_code: 'ja'
|
||||||
json =
|
json =
|
||||||
if host.present?
|
if host.present?
|
||||||
common(post, host:)
|
common(post, host:)
|
||||||
else
|
else
|
||||||
common(post)
|
common(post)
|
||||||
end
|
end
|
||||||
json['tags'] = tag_json(post)
|
json['tags'] = tag_json(post, language_code:)
|
||||||
json['uploaded_user'] = post.uploaded_user && UserRepr.base(post.uploaded_user)
|
json['uploaded_user'] = post.uploaded_user && UserRepr.base(post.uploaded_user)
|
||||||
json['viewed'] = current_user ? current_user.viewed?(post) : false
|
json['viewed'] = current_user ? current_user.viewed?(post) : false
|
||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
def detail post, current_user = nil, parent_posts: [], child_posts: [],
|
def detail post, current_user = nil, parent_posts: [], child_posts: [],
|
||||||
sibling_posts: { }, related: [], host: nil
|
sibling_posts: { }, related: [], host: nil, language_code: 'ja'
|
||||||
if host.present?
|
if host.present?
|
||||||
base(post, current_user, host:).merge(
|
base(post, current_user, host:, language_code:).merge(
|
||||||
'parent_posts' => cards(parent_posts, host:),
|
'parent_posts' => cards(parent_posts, host:),
|
||||||
'child_posts' => cards(child_posts, host:),
|
'child_posts' => cards(child_posts, host:),
|
||||||
'sibling_posts' => sibling_posts.transform_keys(&:to_s).transform_values { |posts|
|
'sibling_posts' => sibling_posts.transform_keys(&:to_s).transform_values { |posts|
|
||||||
@@ -41,7 +41,7 @@ module PostRepr
|
|||||||
},
|
},
|
||||||
'related' => cards(related, host:))
|
'related' => cards(related, host:))
|
||||||
else
|
else
|
||||||
base(post, current_user).merge(
|
base(post, current_user, language_code:).merge(
|
||||||
'parent_posts' => cards(parent_posts),
|
'parent_posts' => cards(parent_posts),
|
||||||
'child_posts' => cards(child_posts),
|
'child_posts' => cards(child_posts),
|
||||||
'sibling_posts' => sibling_posts.transform_keys(&:to_s).transform_values { |posts|
|
'sibling_posts' => sibling_posts.transform_keys(&:to_s).transform_values { |posts|
|
||||||
@@ -86,14 +86,14 @@ module PostRepr
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_json post
|
def tag_json post, language_code:
|
||||||
internal_tags =
|
internal_tags =
|
||||||
post
|
post
|
||||||
.post_tags
|
.post_tags
|
||||||
.reject { _1.tag.deprecated? }
|
.reject { _1.tag.deprecated? }
|
||||||
.sort_by { _1.tag.name('ja') }
|
.sort_by { _1.tag.name(language_code) }
|
||||||
.map { |post_tag|
|
.map { |post_tag|
|
||||||
TagRepr.inline(post_tag.tag).merge(
|
TagRepr.inline(post_tag.tag, language_code:).merge(
|
||||||
'children' => [],
|
'children' => [],
|
||||||
'sections' => post_tag.sections.as_json(only: [:begin_ms, :end_ms]))
|
'sections' => post_tag.sections.as_json(only: [:begin_ms, :end_ms]))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class PostCreatePreflight
|
|||||||
def run locale
|
def run locale
|
||||||
preview = PostImportPreviewer.new.preview_rows(
|
preview = PostImportPreviewer.new.preview_rows(
|
||||||
rows: [preview_row],
|
rows: [preview_row],
|
||||||
|
locale:,
|
||||||
fetch_metadata: false).first
|
fetch_metadata: false).first
|
||||||
if preview[:existing_post_id].present?
|
if preview[:existing_post_id].present?
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class PostImportPreviewer
|
|||||||
THUMBNAIL_FETCH_WARNING = 'サムネールを取得できませんでした.'.freeze
|
THUMBNAIL_FETCH_WARNING = 'サムネールを取得できませんでした.'.freeze
|
||||||
METADATA_FETCH_WARNING = '自動取得に失敗しました.'.freeze
|
METADATA_FETCH_WARNING = '自動取得に失敗しました.'.freeze
|
||||||
|
|
||||||
def preview_rows locale, rows:, fetch_metadata: true, metadata_cache: { }
|
def preview_rows rows:, locale: Locale.nipponese, fetch_metadata: true, metadata_cache: { }
|
||||||
prepared_rows = rows.map { prepare_row(_1) }
|
prepared_rows = rows.map { prepare_row(_1) }
|
||||||
url_counts = prepared_rows.filter_map { _1[:normal_url] }.tally
|
url_counts = prepared_rows.filter_map { _1[:normal_url] }.tally
|
||||||
existing_posts =
|
existing_posts =
|
||||||
@@ -30,6 +30,7 @@ class PostImportPreviewer
|
|||||||
url_counts)
|
url_counts)
|
||||||
known_tags =
|
known_tags =
|
||||||
preload_known_tags(
|
preload_known_tags(
|
||||||
|
locale,
|
||||||
prepared_rows,
|
prepared_rows,
|
||||||
fetch_metadata,
|
fetch_metadata,
|
||||||
metadata_cache,
|
metadata_cache,
|
||||||
@@ -347,7 +348,7 @@ class PostImportPreviewer
|
|||||||
{ data: { }, warnings: { 'url' => [METADATA_FETCH_WARNING] }, validation_errors: { } }
|
{ data: { }, warnings: { 'url' => [METADATA_FETCH_WARNING] }, validation_errors: { } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def preload_known_tags prepared_rows, fetch_metadata, metadata_cache, existing_posts, url_counts
|
def preload_known_tags locale, prepared_rows, fetch_metadata, metadata_cache, existing_posts, url_counts
|
||||||
names = prepared_rows.flat_map { |row|
|
names = prepared_rows.flat_map { |row|
|
||||||
attributes = initial_attributes(row)
|
attributes = initial_attributes(row)
|
||||||
provenance = initial_provenance(row)
|
provenance = initial_provenance(row)
|
||||||
@@ -359,11 +360,11 @@ class PostImportPreviewer
|
|||||||
metadata = metadata_for(row[:normal_url], metadata_cache)
|
metadata = metadata_for(row[:normal_url], metadata_cache)
|
||||||
apply_metadata!(attributes, provenance, tag_sources, metadata[:data])
|
apply_metadata!(attributes, provenance, tag_sources, metadata[:data])
|
||||||
end
|
end
|
||||||
preview_tag_names(merged_tags(tag_sources, provenance['tags']))
|
preview_tag_names(locale, merged_tags(tag_sources, provenance['tags']))
|
||||||
}.compact.uniq
|
}.compact.uniq
|
||||||
return { } if names.empty?
|
return { } if names.empty?
|
||||||
|
|
||||||
TagName.where(language_code: 'ja', primary_flg: true, name: names)
|
TagName.where(language_code: locale.language_code, primary_flg: true, name: names)
|
||||||
.includes(:tag)
|
.includes(:tag)
|
||||||
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag }
|
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
class TagVersionRecorder < VersionRecorder
|
class TagVersionRecorder < VersionRecorder
|
||||||
def self.record! tag:, event_type:, created_by_user:, language_code: 'ja'
|
def self.record! tag:, event_type:, created_by_user:, **_options
|
||||||
new(tag:, event_type:, created_by_user:, language_code:).record!
|
new(tag:, event_type:, created_by_user:).record!
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize tag:, event_type:, created_by_user:, language_code:
|
def initialize tag:, event_type:, created_by_user:
|
||||||
super(record: tag, event_type:, created_by_user:)
|
super(record: tag, event_type:, created_by_user:)
|
||||||
@language_code = language_code
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -15,10 +14,24 @@ class TagVersionRecorder < VersionRecorder
|
|||||||
def record_key = :tag
|
def record_key = :tag
|
||||||
|
|
||||||
def snapshot_attributes
|
def snapshot_attributes
|
||||||
{ name: @record.name(@language_code),
|
names = snapshot_names
|
||||||
|
japanese_names = names.select { _1[:language_code] == 'ja' }
|
||||||
|
compatibility_names = japanese_names.presence || names
|
||||||
|
|
||||||
|
{ name: compatibility_names.find { _1[:primary_flg] }[:name],
|
||||||
category: @record.category,
|
category: @record.category,
|
||||||
deprecated_at: @record.deprecated_at,
|
deprecated_at: @record.deprecated_at,
|
||||||
aliases: @record.snapshot_aliases(@language_code).join(' '),
|
aliases: compatibility_names.reject { _1[:primary_flg] }.map { _1[:name] }.join(' '),
|
||||||
|
names:,
|
||||||
parent_tag_ids: @record.snapshot_parent_tag_ids.join(' ') }
|
parent_tag_ids: @record.snapshot_parent_tag_ids.join(' ') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def snapshot_names
|
||||||
|
@record.tag_names.order(:language_code, primary_flg: :desc).order(:name).map { |tag_name|
|
||||||
|
{ language_code: tag_name.language_code,
|
||||||
|
name: tag_name.name,
|
||||||
|
script_code: tag_name.script_code,
|
||||||
|
primary_flg: tag_name.primary_flg }
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
class AddNamesToTagVersions < ActiveRecord::Migration[8.0]
|
||||||
|
class TagVersion < ActiveRecord::Base
|
||||||
|
self.table_name = 'tag_versions'
|
||||||
|
end
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_column :tag_versions, :names, :json
|
||||||
|
TagVersion.reset_column_information
|
||||||
|
|
||||||
|
say_with_time 'Backfilling multilingual tag version names' do
|
||||||
|
TagVersion.find_each do |version|
|
||||||
|
names = [{
|
||||||
|
language_code: 'ja',
|
||||||
|
name: version.name,
|
||||||
|
script_code: 'Jpan',
|
||||||
|
primary_flg: true }]
|
||||||
|
names.concat(version.aliases.to_s.split.filter_map { |name|
|
||||||
|
next if name.blank?
|
||||||
|
|
||||||
|
{
|
||||||
|
language_code: 'ja',
|
||||||
|
name:,
|
||||||
|
script_code: 'Jpan',
|
||||||
|
primary_flg: false }
|
||||||
|
})
|
||||||
|
version.update_columns(names: names)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
change_column_null :tag_versions, :names, false
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :tag_versions, :names
|
||||||
|
end
|
||||||
|
end
|
||||||
生成ファイル
+2
-1
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2026_09_22_030000) do
|
ActiveRecord::Schema[8.0].define(version: 2026_09_22_040000) do
|
||||||
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@@ -480,6 +480,7 @@ ActiveRecord::Schema[8.0].define(version: 2026_09_22_030000) do
|
|||||||
t.datetime "deprecated_at"
|
t.datetime "deprecated_at"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.bigint "created_by_user_id"
|
t.bigint "created_by_user_id"
|
||||||
|
t.json "names", null: false
|
||||||
t.index ["created_at"], name: "index_tag_versions_on_created_at"
|
t.index ["created_at"], name: "index_tag_versions_on_created_at"
|
||||||
t.index ["created_by_user_id", "created_at"], name: "index_tag_versions_on_created_by_user_id_and_created_at", order: { created_at: :desc }
|
t.index ["created_by_user_id", "created_at"], name: "index_tag_versions_on_created_by_user_id_and_created_at", order: { created_at: :desc }
|
||||||
t.index ["tag_id", "created_at"], name: "index_tag_versions_on_tag_id_and_created_at", order: { created_at: :desc }
|
t.index ["tag_id", "created_at"], name: "index_tag_versions_on_tag_id_and_created_at", order: { created_at: :desc }
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ RSpec.describe VersionRecord, type: :model do
|
|||||||
name: primary_tag_name_for(tag, 'ja').name,
|
name: primary_tag_name_for(tag, 'ja').name,
|
||||||
category: tag.category,
|
category: tag.category,
|
||||||
aliases: '',
|
aliases: '',
|
||||||
|
names: [{ language_code: 'ja', name: primary_tag_name_for(tag, 'ja').name,
|
||||||
|
script_code: 'Jpan', primary_flg: true }],
|
||||||
parent_tag_ids: '',
|
parent_tag_ids: '',
|
||||||
created_at: Time.current,
|
created_at: Time.current,
|
||||||
created_by_user: nil
|
created_by_user: nil
|
||||||
@@ -30,6 +32,8 @@ RSpec.describe VersionRecord, type: :model do
|
|||||||
name: primary_tag_name_for(tag, 'ja').name,
|
name: primary_tag_name_for(tag, 'ja').name,
|
||||||
category: tag.category,
|
category: tag.category,
|
||||||
aliases: '',
|
aliases: '',
|
||||||
|
names: [{ language_code: 'ja', name: primary_tag_name_for(tag, 'ja').name,
|
||||||
|
script_code: 'Jpan', primary_flg: true }],
|
||||||
parent_tag_ids: '',
|
parent_tag_ids: '',
|
||||||
created_at: Time.current,
|
created_at: Time.current,
|
||||||
created_by_user: nil
|
created_by_user: nil
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ RSpec.describe 'TagVersions API', type: :request do
|
|||||||
category: category,
|
category: category,
|
||||||
deprecated_at: deprecated_at,
|
deprecated_at: deprecated_at,
|
||||||
aliases: Array(aliases).join(' '),
|
aliases: Array(aliases).join(' '),
|
||||||
|
names: [{ language_code: 'ja', name: name, script_code: 'Jpan',
|
||||||
|
primary_flg: true }] + Array(aliases).map { |alias_name|
|
||||||
|
{ language_code: 'ja', name: alias_name, script_code: 'Jpan',
|
||||||
|
primary_flg: false }
|
||||||
|
},
|
||||||
parent_tag_ids: Array(parent_tags).map(&:id).join(' '),
|
parent_tag_ids: Array(parent_tags).map(&:id).join(' '),
|
||||||
created_by_user: created_by_user,
|
created_by_user: created_by_user,
|
||||||
created_at: created_at)
|
created_at: created_at)
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe TagVersionRecorder do
|
||||||
|
let(:user) { create_member_user! }
|
||||||
|
let(:tag) { create(:tag, primary_name: '日本語名') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Language.insert_all!([{ code: 'en', name: 'English', created_at: Time.current }])
|
||||||
|
Script.insert_all!([{ code: 'Latn', name: 'Latin', created_at: Time.current }])
|
||||||
|
Locale.insert_all!([{ code: 'en', language_code: 'en', script_code: 'Latn',
|
||||||
|
name: 'English', created_at: Time.current }])
|
||||||
|
TagName.create!(tag:, language_code: 'ja', script_code: 'Jpan', name: '別名',
|
||||||
|
primary_flg: false,
|
||||||
|
canonical_id: tag.tag_name_id)
|
||||||
|
TagName.create!(tag:, language_code: 'en', script_code: 'Latn', name: 'English name',
|
||||||
|
primary_flg: true)
|
||||||
|
TagName.create!(tag:, language_code: 'en', script_code: 'Latn', name: 'English alias',
|
||||||
|
primary_flg: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'snapshots every language primary name and alias deterministically' do
|
||||||
|
version = described_class.record!(tag:, event_type: :create, created_by_user: user)
|
||||||
|
|
||||||
|
expect(version.names).to eq([
|
||||||
|
{ 'language_code' => 'en', 'name' => 'English name', 'script_code' => 'Latn',
|
||||||
|
'primary_flg' => true },
|
||||||
|
{ 'language_code' => 'en', 'name' => 'English alias', 'script_code' => 'Latn',
|
||||||
|
'primary_flg' => false },
|
||||||
|
{ 'language_code' => 'ja', 'name' => '日本語名', 'script_code' => 'Jpan',
|
||||||
|
'primary_flg' => true },
|
||||||
|
{ 'language_code' => 'ja', 'name' => '別名', 'script_code' => 'Jpan',
|
||||||
|
'primary_flg' => false }
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a version for an English-only name change and preserves prior names' do
|
||||||
|
original = described_class.record!(tag:, event_type: :create, created_by_user: user)
|
||||||
|
TagName.find_by!(tag:, language_code: 'en', primary_flg: true).update!(name: 'Renamed')
|
||||||
|
|
||||||
|
updated = described_class.record!(tag:, event_type: :update, created_by_user: user)
|
||||||
|
|
||||||
|
expect(updated.version_no).to eq(2)
|
||||||
|
expect(original.reload.names).to include(
|
||||||
|
hash_including('language_code' => 'en', 'name' => 'English name'))
|
||||||
|
expect(updated.names).to include(hash_including('language_code' => 'en', 'name' => 'Renamed'))
|
||||||
|
end
|
||||||
|
end
|
||||||
新しいイシューから参照
ユーザーをブロックする