From a7020fb129c5694d0a45076f5400102ea84ce9e2 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Wed, 29 Apr 2026 05:19:46 +0900 Subject: [PATCH] #46 --- backend/app/controllers/posts_controller.rb | 55 ++++++++++++++++++- backend/app/controllers/tags_controller.rb | 6 +- backend/app/models/post.rb | 4 ++ backend/app/models/tag.rb | 6 +- backend/app/representations/post_repr.rb | 3 +- backend/app/services/post_version_recorder.rb | 2 +- 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/backend/app/controllers/posts_controller.rb b/backend/app/controllers/posts_controller.rb index 111052b..cfb0cbd 100644 --- a/backend/app/controllers/posts_controller.rb +++ b/backend/app/controllers/posts_controller.rb @@ -123,6 +123,7 @@ class PostsController < ApplicationController tag_names = params[:tags].to_s.split original_created_from = params[:original_created_from] original_created_before = params[:original_created_before] + parent_post_ids = parse_parent_post_ids post = Post.new(title:, url:, thumbnail_base: nil, uploaded_user: current_user, original_created_from:, original_created_before:) @@ -130,17 +131,24 @@ class PostsController < ApplicationController ApplicationRecord.transaction do post.save! - tags = Tag.normalise_tags(tag_names) + + tags = Tag.normalise_tags!(tag_names) TagVersioning.record_tag_snapshots!(tags, created_by_user: current_user) tags = Tag.expand_parent_tags(tags) sync_post_tags!(post, tags) + + sync_parent_posts!(post, parent_post_ids) + post.resized_thumbnail! + PostVersionRecorder.record!(post:, event_type: :create, created_by_user: current_user) end post.reload render json: PostRepr.base(post), status: :created + rescue ArgumentError => e + render json: { errors: [e.message] }, status: :unprocessable_entity rescue ActiveRecord::RecordInvalid render json: { errors: post.errors.full_messages }, status: :unprocessable_entity rescue Tag::NicoTagNormalisationError @@ -169,6 +177,7 @@ class PostsController < ApplicationController tag_names = params[:tags].to_s.split original_created_from = params[:original_created_from] original_created_before = params[:original_created_before] + parent_post_ids = parse_parent_post_ids post = Post.find(params[:id].to_i) @@ -177,12 +186,15 @@ class PostsController < ApplicationController post.update!(title:, original_created_from:, original_created_before:) - normalised_tags = Tag.normalise_tags(tag_names, with_tagme: false) + normalised_tags = Tag.normalise_tags!(tag_names, with_tagme: false) TagVersioning.record_tag_snapshots!(normalised_tags, created_by_user: current_user) tags = post.tags.nico.to_a + normalised_tags tags = Tag.expand_parent_tags(tags) sync_post_tags!(post, tags) + + sync_parent_posts!(post, parent_post_ids) + PostVersionRecorder.record!(post:, event_type: :update, created_by_user: current_user) end @@ -190,6 +202,8 @@ class PostsController < ApplicationController json = post.as_json json['tags'] = build_tag_tree_for(post.tags) render json:, status: :ok + rescue ArgumentError => e + render json: { errors: [e.message] }, status: :unprocessable_entity rescue ActiveRecord::RecordInvalid render json: post.errors, status: :unprocessable_entity rescue Tag::NicoTagNormalisationError @@ -353,4 +367,41 @@ class PostsController < ApplicationController root_ids.filter_map { |id| build_node.call(id, []) } end + + def parse_parent_post_ids + raise ArgumentError, 'parent_post_ids は必須です.' unless params.key?(:parent_post_ids) + + params[:parent_post_ids].to_s.split.map { |token| + id = Integer(token, exception: false) + raise ArgumentError, "親投稿 Id. が不正です: #{ token }" if id.nil? || id <= 0 + + id + }.uniq + end + + def sync_parent_posts! post, parent_post_ids + if parent_post_ids.include?(post.id) + post.errors.add(:base, '自分自身を親投稿にはできません.') + raise ActiveRecord::RecordInvalid, post + end + + existing_ids = Post.where(id: parent_post_ids).pluck(:id) + missing_ids = parent_post_ids - existing_ids + + if missing_ids.present? + post.errors.add(:base, "存在しない親投稿 ID があります: #{ missing_ids.join(' ') }") + raise ActiveRecord::RecordInvalid, post + end + + current_ids = post.parent_posts.pluck(:id) + + ids_to_add = parent_post_ids - current_ids + ids_to_remove = current_ids - parent_post_ids + + PostImplication.where(post_id: post.id, parent_post_id: ids_to_remove).delete_all + + ids_to_add.each do |parent_post_id| + PostImplication.create_or_find_by!(post_id: post.id, parent_post_id:) + end + end end diff --git a/backend/app/controllers/tags_controller.rb b/backend/app/controllers/tags_controller.rb index 3560e81..9b8bbe9 100644 --- a/backend/app/controllers/tags_controller.rb +++ b/backend/app/controllers/tags_controller.rb @@ -374,9 +374,9 @@ class TagsController < ApplicationController end def update_parent_tags! tag, parent_names - parent_tags = Tag.normalise_tags(parent_names, with_tagme: false, - with_no_deerjikist: false, - deny_nico: true) + parent_tags = Tag.normalise_tags!(parent_names, with_tagme: false, + with_no_deerjikist: false, + deny_nico: true) old_parent_tags = tag.parents.to_a diff --git a/backend/app/models/post.rb b/backend/app/models/post.rb index 57fa351..63c23d2 100644 --- a/backend/app/models/post.rb +++ b/backend/app/models/post.rb @@ -35,6 +35,8 @@ class Post < ApplicationRecord validate :validate_original_created_range validate :url_must_be_http_url + def parent_posts = parents + def as_json options = { } super(options).merge({ thumbnail: thumbnail.attached? ? Rails.application.routes.url_helpers.rails_blob_url( @@ -46,6 +48,8 @@ class Post < ApplicationRecord def snapshot_tag_names = tags.joins(:tag_name).order('tag_names.name').pluck('tag_names.name') + def snapshot_parent_post_ids = parents.order(:parent_post_id).pulck(:parent_post_id) + def related limit: nil ids = post_similarities.order(cos: :desc) ids = ids.limit(limit) if limit diff --git a/backend/app/models/tag.rb b/backend/app/models/tag.rb index 54c3d68..36450b4 100644 --- a/backend/app/models/tag.rb +++ b/backend/app/models/tag.rb @@ -85,9 +85,9 @@ class Tag < ApplicationRecord def self.video = find_or_create_by_tag_name!('動画', category: :meta) def self.niconico = find_or_create_by_tag_name!('ニコニコ', category: :meta) - def self.normalise_tags tag_names, with_tagme: true, - with_no_deerjikist: true, - deny_nico: true + def self.normalise_tags! tag_names, with_tagme: true, + with_no_deerjikist: true, + deny_nico: true if deny_nico && tag_names.any? { |n| n.downcase.start_with?('nico:') } raise NicoTagNormalisationError end diff --git a/backend/app/representations/post_repr.rb b/backend/app/representations/post_repr.rb index bcba375..b77d0b8 100644 --- a/backend/app/representations/post_repr.rb +++ b/backend/app/representations/post_repr.rb @@ -2,7 +2,8 @@ module PostRepr - BASE = { include: { tags: TagRepr::BASE, uploaded_user: UserRepr::BASE } }.freeze + BASE = { include: { tags: TagRepr::BASE, uploaded_user: UserRepr::BASE }, + methods: [:parent_posts] }.freeze module_function diff --git a/backend/app/services/post_version_recorder.rb b/backend/app/services/post_version_recorder.rb index 515d1d8..9e3fd15 100644 --- a/backend/app/services/post_version_recorder.rb +++ b/backend/app/services/post_version_recorder.rb @@ -24,7 +24,7 @@ class PostVersionRecorder < VersionRecorder url: @record.url, thumbnail_base: @record.thumbnail_base, tags: @record.snapshot_tag_names.join(' '), - parent_id: @record.parent_id, + parent_post_ids: @record.snapshot_parent_post_ids.join(' '), original_created_from: @record.original_created_from, original_created_before: @record.original_created_before } end