From 1d1787312f94b074c1c96ad0cceaf1fd60e25945 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Tue, 28 Apr 2026 00:55:14 +0900 Subject: [PATCH] #46 --- backend/app/models/post.rb | 15 +++++++++++- backend/app/models/post_implication.rb | 19 +++++++++++++++ ...20260427214800_create_post_implications.rb | 24 +++++++++++++++++++ backend/db/schema.rb | 20 ++++++++++------ frontend/src/pages/posts/PostDetailPage.tsx | 1 + 5 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 backend/app/models/post_implication.rb create mode 100644 backend/db/migrate/20260427214800_create_post_implications.rb diff --git a/backend/app/models/post.rb b/backend/app/models/post.rb index 901b1e3..57fa351 100644 --- a/backend/app/models/post.rb +++ b/backend/app/models/post.rb @@ -1,7 +1,6 @@ class Post < ApplicationRecord require 'mini_magick' - belongs_to :parent, class_name: 'Post', optional: true, foreign_key: 'parent_id' belongs_to :uploaded_user, class_name: 'User', optional: true has_many :post_tags, dependent: :destroy, inverse_of: :post @@ -13,6 +12,20 @@ class Post < ApplicationRecord has_many :post_similarities, dependent: :delete_all has_many :post_versions + has_many :parent_post_implications, + class_name: 'PostImplication', + foreign_key: :post_id, + dependent: :destroy, + inverse_of: :post + has_many :parents, through: :parent_post_implications, source: :parent_post + + has_many :child_post_implications, + class_name: 'PostImplication', + foreign_key: :parent_post_id, + dependent: :destroy, + inverse_of: :parent_post + has_many :children, through: :child_post_implications, source: :post + has_one_attached :thumbnail before_validation :normalise_url diff --git a/backend/app/models/post_implication.rb b/backend/app/models/post_implication.rb new file mode 100644 index 0000000..21c5a59 --- /dev/null +++ b/backend/app/models/post_implication.rb @@ -0,0 +1,19 @@ +class PostImplication < ApplicationRecord + self.primary_key = :post_id, :parent_post_id + + belongs_to :post, inverse_of: :parent_post_implications + belongs_to :parent_post, class_name: 'Post', inverse_of: :child_post_implications + + validates :post_id, presence: true, uniqueness: { scope: :parent_post_id } + validates :parent_post_id, presence: true + + validate :parent_post_mustnt_be_itself + + private + + def parent_post_mustnt_be_itself + if parent_post_id == post_id + errors.add :parent_post_id, '親投稿に同じ投稿を設定することはできません.' + end + end +end diff --git a/backend/db/migrate/20260427214800_create_post_implications.rb b/backend/db/migrate/20260427214800_create_post_implications.rb new file mode 100644 index 0000000..b0a666f --- /dev/null +++ b/backend/db/migrate/20260427214800_create_post_implications.rb @@ -0,0 +1,24 @@ +class CreatePostImplications < ActiveRecord::Migration[8.0] + def up + create_table :post_implications, primary_key: [:post_id, :parent_post_id] do |t| + t.references :post, null: false, foreign_key: true, index: false + t.references :parent_post, null: false, foreign_key: { to_table: :posts } + t.timestamps + + t.check_constraint 'post_id <> parent_post_id', + name: 'chk_post_implications_no_self' + end + + add_column :post_versions, :parent_post_ids, :text, null: false, after: :parent_id + remove_column :post_versions, :parent_id, :bigint + remove_reference :posts, :parent, foreign_key: { to_table: :posts } + end + + def down + add_reference :posts, :parent, foreign_key: { to_table: :posts }, after: :thumbnail_base + add_column :post_versions, :parent_id, :bigint, after: :post_id + remove_column :post_versions, :parent_post_ids, :text + + drop_table :post_implications + end +end diff --git a/backend/db/schema.rb b/backend/db/schema.rb index 6e1a67f..48ee45f 100644 --- a/backend/db/schema.rb +++ b/backend/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2026_04_26_120600) do +ActiveRecord::Schema[8.0].define(version: 2026_04_27_214800) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -119,6 +119,15 @@ ActiveRecord::Schema[8.0].define(version: 2026_04_26_120600) do t.check_constraint "`version_no` > 0", name: "nico_tag_versions_version_no_positive" end + create_table "post_implications", primary_key: ["post_id", "parent_post_id"], charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "post_id", null: false + t.bigint "parent_post_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["parent_post_id"], name: "index_post_implications_on_parent_post_id" + t.check_constraint "`post_id` <> `parent_post_id`", name: "chk_post_implications_no_self" + end + create_table "post_similarities", primary_key: ["post_id", "target_post_id"], charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "post_id", null: false t.bigint "target_post_id", null: false @@ -155,13 +164,12 @@ ActiveRecord::Schema[8.0].define(version: 2026_04_26_120600) do t.string "url", limit: 768, null: false t.string "thumbnail_base", limit: 2000 t.text "tags", null: false - t.bigint "parent_id" + t.text "parent_post_ids", null: false t.datetime "original_created_from" t.datetime "original_created_before" t.datetime "created_at", null: false t.bigint "created_by_user_id" t.index ["created_by_user_id"], name: "index_post_versions_on_created_by_user_id" - t.index ["parent_id"], name: "index_post_versions_on_parent_id" t.index ["post_id", "version_no"], name: "index_post_versions_on_post_id_and_version_no", unique: true t.index ["post_id"], name: "index_post_versions_on_post_id" t.check_constraint "`event_type` in (_utf8mb4'create',_utf8mb4'update',_utf8mb4'discard',_utf8mb4'restore')", name: "post_versions_event_type_valid" @@ -172,13 +180,11 @@ ActiveRecord::Schema[8.0].define(version: 2026_04_26_120600) do t.string "title" t.string "url", limit: 768, null: false t.string "thumbnail_base", limit: 2000 - t.bigint "parent_id" t.bigint "uploaded_user_id" t.datetime "created_at", null: false t.datetime "original_created_from" t.datetime "original_created_before" t.datetime "updated_at", null: false - t.index ["parent_id"], name: "index_posts_on_parent_id" t.index ["uploaded_user_id"], name: "index_posts_on_uploaded_user_id" t.index ["url"], name: "index_posts_on_url", unique: true end @@ -428,6 +434,8 @@ ActiveRecord::Schema[8.0].define(version: 2026_04_26_120600) do add_foreign_key "nico_tag_relations", "tags", column: "nico_tag_id" add_foreign_key "nico_tag_versions", "tags" add_foreign_key "nico_tag_versions", "users", column: "created_by_user_id" + add_foreign_key "post_implications", "posts" + add_foreign_key "post_implications", "posts", column: "parent_post_id" add_foreign_key "post_similarities", "posts" add_foreign_key "post_similarities", "posts", column: "target_post_id" add_foreign_key "post_tags", "posts" @@ -435,9 +443,7 @@ ActiveRecord::Schema[8.0].define(version: 2026_04_26_120600) do add_foreign_key "post_tags", "users", column: "created_user_id" add_foreign_key "post_tags", "users", column: "deleted_user_id" add_foreign_key "post_versions", "posts" - add_foreign_key "post_versions", "posts", column: "parent_id" add_foreign_key "post_versions", "users", column: "created_by_user_id" - add_foreign_key "posts", "posts", column: "parent_id" add_foreign_key "posts", "users", column: "uploaded_user_id" add_foreign_key "settings", "users" add_foreign_key "tag_implications", "tags" diff --git a/frontend/src/pages/posts/PostDetailPage.tsx b/frontend/src/pages/posts/PostDetailPage.tsx index 50a19d9..433d312 100644 --- a/frontend/src/pages/posts/PostDetailPage.tsx +++ b/frontend/src/pages/posts/PostDetailPage.tsx @@ -108,6 +108,7 @@ export default (({ user }: Props) => { {post ? ( <> + {/* TODO: 親投稿リスト */} {(post.thumbnail || post.thumbnailBase) && (